create a fixed sized widget on flutter - flutter

I'm currently trying to create a row that consist of maximum 3 column widget with each of them have the property of profile picture, nickname, and status. I wanted each of them to have fixed size so that even when the nickname is long it will still take the same amount of space.
Currently I just make the column to be spaced-evenly and some of the widget still take more space than the other 2. How can I fixed this ? maybe make the nickname turned into dotted (...) when it's too long.
here's my current code:
solverWidgets.add(
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BuildRoundedRectProfile(
height: 40,
width: 40,
name: solverTicket[solver]['nickname'],
profileLink: solverTicket[solver]['profile_picture_link'] ?? '',
),
SizedBox(height: 3),
Text(
solverTicket[solver]['nickname'],
style: weight600Style.copyWith(
color: primaryColor,
fontSize: 13,
),
),
if (solversStatus[solver] != null && (povStatus == 'pic' || povStatus == 'pic-client'))
GestureDetector(
onTap: () {
if (solversStatus[solver] == 'Done') {
setState(() {
needToLoadSolverWidgets = true;
isNotExpandedSolverWidgets[solver] = !isNotExpandedSolverWidgets[solver];
});
if (isExpandedSolverWidgetsContent[solver]) {
Future.delayed(Duration(milliseconds: 300), () {
setState(() {
needToLoadSolverWidgets = true;
isExpandedSolverWidgetsContent[solver] = false;
});
});
} else {
setState(() {
needToLoadSolverWidgets = true;
isExpandedSolverWidgetsContent[solver] = true;
});
}
}
},
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
height: isNotExpandedSolverWidgets[solver] ? 20 : 55,
padding: EdgeInsets.only(top: 5, bottom: 5, left: 5, right: 5),
decoration: BoxDecoration(
color: defaultProfileColor.withOpacity(0.2),
borderRadius: BorderRadius.circular(10),
),
child: solversStatus[solver] != 'Done' ?
Text(
solversStatus[solver],
style: primaryColor600Style.copyWith(
fontSize: fontSize9,
),
).tr() : isNotExpandedSolverWidgets[solver] ?
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
solversStatus[solver],
style: primaryColor600Style.copyWith(
fontSize: fontSize10,
),
).tr(),
Icon(
Icons.arrow_drop_down,
size: fontSize15,
),
],
) : ClipRRect(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
children: [
Text(
solversStatus[solver],
style: primaryColor600Style
.copyWith(
fontSize: fontSize9,
),
).tr(),
Icon(
Icons.arrow_drop_down,
size: fontSize18,
),
],
),
GestureDetector(
onTap: () {
showDialog(
context: context,
builder: (BuildContext
context) =>
ReusableConfirmationDialog(
titleText: 'changeWorkStatus'.tr(),
contentText: 'rejectWorkStatus'.tr(),
confirmButtonText: 'yes'.tr(),
onConfirm: () async {
await Database.changeWorkStatus(
ticketId: widget.ticketId,
ticketData: ticketData,
targetId: solver as String,
oldWorkStatus: 'done',
workStatus: 'todo');
Navigator.pop(context);
setState(() {
isNotExpandedSolverWidgets[solver] = true;
needToLoadTicket = true;
});
}));
},
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
color: warningColor,
borderRadius:
BorderRadius.circular(5),
),
child: Text(
'disagree',
style: primaryColor600Style
.copyWith(
fontSize: fontSize9,
color: Colors.white,
),
).tr(),
),
)
]),
),
),
),
if(solversStatus[solver] != null && (povStatus != 'pic' && povStatus != 'pic-client'))
Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
color: formBackgroundColor,
borderRadius: BorderRadius.all(
Radius.circular(10))),
child: Text(
solversStatus[solver],
style: weight600Style.copyWith(
color: primaryColor,
fontSize: 9,
),
),
),
],
),
);

use Text overflow
Text(
'You have pushed the button this many times:dfjhejh dskfjkawejfkjadshfkljhaskdfhekjnkjvnkjasdklfjjekjlkj',
maxLines: 1,
overflow: TextOverflow.ellipsis,
)

or You can use https://pub.dev/packages/marquee package, it will scroll your text infinitly. make sure to wrap this marquee widget in a sizedbox with height and width defined.

Related

Why is my flutter widgets not working when in a different state management

I bought an online template app and i am trying to hardcode my email and password credentials in my flutter frontend because i don't have access to the backend api yet to change from email/password auth to phone auth, so i want to force code the logic into my flutter widget.
This means i am trying to implement the onPressed: () { controller.login(); }, function on a login button to get me to the home screen with my customized widget.
The original code given to me works fine when i hardcode the credentials in the text form field but when i hardcode the text form field in my customized widget and use same onPressed: () { controller.login(); }, function it don't work.
I want to know if it's because of i'm in a different state management or there's something i'm failing to do.
I will give the original code and my customized UI code in the snippets for comparison.
PS: i even tried to use same text form field in my widget but hide it with Visibility() in flutter. When i use Visibility() in the original code, onPressed: () { controller.login(); }, works but when i use it in my customized widget, it doest.
How do work around this? If you need more clarification, i am willing to offer. Thanks.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../../../common/helper.dart';
import '../../../../../common/ui.dart';
import '../../../../models/setting_model.dart';
import '../../../../routes/app_routes.dart';
import '../../../../services/settings_service.dart';
import '../../../global_widgets/block_button_widget.dart';
import '../../../global_widgets/circular_loading_widget.dart';
import '../../../global_widgets/text_field_widget.dart';
import '../../controllers/auth_controller.dart';
class LoginView extends GetView<AuthController> {
final Setting _settings = Get.find<SettingsService>().setting.value;
#override
Widget build(BuildContext context) {
controller.loginFormKey = new GlobalKey<FormState>();
return Visibility(
visible: false,
child: WillPopScope(
onWillPop: Helper().onWillPop,
child: Scaffold(
appBar: AppBar(
title: Text(
"Login".tr,
style: Get.textTheme.headline6
.merge(TextStyle(color: context.theme.primaryColor)),
),
centerTitle: true,
backgroundColor: Get.theme.colorScheme.secondary,
automaticallyImplyLeading: false,
elevation: 0,
),
body: Form(
key: controller.loginFormKey,
child: ListView(
primary: true,
children: [
Stack(
alignment: AlignmentDirectional.bottomCenter,
children: [
Container(
height: 180,
width: Get.width,
decoration: BoxDecoration(
color: Get.theme.colorScheme.secondary,
borderRadius:
BorderRadius.vertical(bottom: Radius.circular(10)),
boxShadow: [
BoxShadow(
color: Get.theme.focusColor.withOpacity(0.2),
blurRadius: 10,
offset: Offset(0, 5)),
],
),
margin: EdgeInsets.only(bottom: 50),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Text(
_settings.salonAppName,
style: Get.textTheme.headline6.merge(TextStyle(
color: Get.theme.primaryColor, fontSize: 24)),
),
SizedBox(height: 5),
Text(
"Welcome to the best salon service system!".tr,
style: Get.textTheme.caption.merge(
TextStyle(color: Get.theme.primaryColor)),
textAlign: TextAlign.center,
),
// Text("Fill the following credentials to login your account", style: Get.textTheme.caption.merge(TextStyle(color: Get.theme.primaryColor))),
],
),
),
),
Container(
decoration: Ui.getBoxDecoration(
radius: 14,
border:
Border.all(width: 5, color: Get.theme.primaryColor),
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: Image.asset(
'assets/icon/icon.png',
fit: BoxFit.cover,
width: 100,
height: 100,
),
),
),
],
),
Obx(() {
if (controller.loading.isTrue)
return CircularLoadingWidget(height: 300);
else {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Visibility(
visible: false,
maintainState: true,
child: TextFieldWidget(
labelText: "Email Address".tr,
hintText: "johndoe#gmail.com".tr,
initialValue: 'salon#demo.com',
onSaved: (input) =>
controller.currentUser.value.email = input,
validator: (input) => !input.contains('#')
? "Should be a valid email".tr
: null,
iconData: Icons.alternate_email,
),
),
Obx(() {
return Visibility(
visible: false,
maintainState: true,
child: TextFieldWidget(
labelText: "Password".tr,
hintText: "••••••••••••".tr,
initialValue: '123456',
onSaved: (input) =>
controller.currentUser.value.password = input,
validator: (input) => input.length < 3
? "Should be more than 3 characters".tr
: null,
),
);
}),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
Get.toNamed(Routes.FORGOT_PASSWORD);
},
child: Text("Forgot Password?".tr),
),
],
).paddingSymmetric(horizontal: 20),
BlockButtonWidget(
onPressed: () {
controller.login();
},
color: Get.theme.colorScheme.secondary,
text: Text(
"Login".tr,
style: Get.textTheme.headline6.merge(
TextStyle(color: Get.theme.primaryColor)),
),
).paddingSymmetric(vertical: 10, horizontal: 20),
TextButton(
onPressed: () {
//Get.toNamed(Routes.REGISTER);
},
child: Text("You don't have an account?".tr),
).paddingOnly(top: 20),
GestureDetector(
onTap: () {
Get.toNamed(Routes.SETTINGS_LANGUAGE);
},
child: Text(
Get.locale.toString().tr,
textAlign: TextAlign.center,
),
),
],
);
}
}),
],
),
),
),
),
);
}
}
THIS IS THE ORIGINAL WIDGET CODE
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../../routes/app_routes.dart';
import '../../../global_widgets/circular_loading_widget.dart';
import '../../../global_widgets/text_field_widget.dart';
import '../../controllers/auth_controller.dart';
import 'login_view.dart';
import 'pin_number.dart';
import 'keyboard_number.dart';
class PinScreen extends StatefulWidget {
const PinScreen({Key key}) : super(key: key);
#override
State<PinScreen> createState() => _PinScreenState();
}
class _PinScreenState extends State<PinScreen> {
List<String> currentPin = ["", "", "", ""];
TextEditingController pinOneController = TextEditingController();
TextEditingController pinTwoController = TextEditingController();
TextEditingController pinThreeController = TextEditingController();
TextEditingController pinFourController = TextEditingController();
var outlineInputBorder = OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.transparent),
);
int pinIndex = 0;
#override
Widget build(BuildContext context) {
final controller = Get.find<AuthController>();
controller.loginFormKey = new GlobalKey<FormState>();
return Form(
key: controller.loginFormKey,
child: SafeArea(
child: Column(
children: [
buildExitButton(),
Obx(() {
if (controller.loading.isTrue)
return CircularLoadingWidget(height: 300);
else {
return Expanded(
child: Container(
alignment: Alignment(0, 0.5),
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
buildSecurityText(),
SizedBox(height: 20.0),
buildPinRow(),
SizedBox(height: 10.0),
buildNumberPad(),
SizedBox(height: 20.0),
Visibility(
visible: false,
maintainState: true,
child: TextFieldWidget(
labelText: "Email Address".tr,
hintText: "johndoe#gmail.com".tr,
initialValue: 'salon#demo.com',
validator: (input) => !input.contains('#')
? "Should be a valid email".tr
: null,
iconData: Icons.alternate_email,
),
),
Obx(() {
return Visibility(
visible: false,
maintainState: true,
child: TextFieldWidget(
labelText: "Password".tr,
hintText: "••••••••••••".tr,
initialValue: '123456',
validator: (input) => input.length < 3
? "Should be more than 3 characters".tr
: null,
iconData: Icons.lock_outline,
keyboardType: TextInputType.visiblePassword,
suffixIcon: IconButton(
onPressed: () {
controller.hidePassword.value =
!controller.hidePassword.value;
},
color: Theme.of(context).focusColor,
icon: Icon(controller.hidePassword.value
? Icons.visibility_outlined
: Icons.visibility_off_outlined),
),
),
);
}),
Container(
child: new RichText(
text: new TextSpan(
children: [
new TextSpan(
recognizer: TapGestureRecognizer()
..onTap = () {
// Get.toNamed(Routes.REGISTER);
},
text: 'Forgot Pin ?',
style: new TextStyle(
color: Color(0xff3498DB),
fontSize: 14,
fontWeight: FontWeight.w500),
),
],
),
),
),
SizedBox(height: 20.0),
MaterialButton(
onPressed: () {
controller.login();
},
color: Color(0xff34495E),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.18),
),
padding: EdgeInsets.symmetric(
horizontal: 30, vertical: 10),
minWidth: double.infinity,
child: Text(
'Next',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600),
),
),
SizedBox(height: 32.0),
],
),
),
);
}
})
],
),
),
);
}
buildNumberPad() {
return Expanded(
child: Container(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
KeyboardNumber(
n: 1,
onPressed: () {
pinIndexSetup("1");
},
),
KeyboardNumber(
n: 2,
onPressed: () {
pinIndexSetup("2");
},
),
KeyboardNumber(
n: 3,
onPressed: () {
pinIndexSetup("3");
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
KeyboardNumber(
n: 4,
onPressed: () {
pinIndexSetup("4");
},
),
KeyboardNumber(
n: 5,
onPressed: () {
pinIndexSetup("5");
},
),
KeyboardNumber(
n: 6,
onPressed: () {
pinIndexSetup("6");
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
KeyboardNumber(
n: 7,
onPressed: () {
pinIndexSetup("7");
},
),
KeyboardNumber(
n: 8,
onPressed: () {
pinIndexSetup("8");
},
),
KeyboardNumber(
n: 9,
onPressed: () {
pinIndexSetup("9");
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 60.0,
child: MaterialButton(
onPressed: null,
child: SizedBox(),
),
),
KeyboardNumber(
n: 0,
onPressed: () {
pinIndexSetup("0");
},
),
Container(
width: 60.0,
child: MaterialButton(
onPressed: () {
clearPin();
},
height: 60.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(60.0),
),
child: Image.asset(
'assets/icon/clear-symbol.png',
),
),
)
],
),
],
),
),
),
);
}
clearPin() {
if (pinIndex == 0)
pinIndex = 0;
else if (pinIndex == 4) {
setPin(pinIndex, "");
currentPin[pinIndex - 1] = "";
pinIndex--;
} else {
setPin(pinIndex, "");
currentPin[pinIndex - 1] = "";
pinIndex--;
}
}
pinIndexSetup(String text) {
if (pinIndex == 0)
pinIndex = 1;
else if (pinIndex < 4) pinIndex++;
setPin(pinIndex, text);
currentPin[pinIndex - 1] = text;
String strPin = "";
currentPin.forEach((e) {
strPin += e;
});
if (pinIndex == 4) print(strPin);
}
setPin(int n, String text) {
switch (n) {
case 1:
pinOneController.text = text;
break;
case 2:
pinTwoController.text = text;
break;
case 3:
pinThreeController.text = text;
break;
case 4:
pinFourController.text = text;
break;
}
}
buildExitButton() {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: MaterialButton(
onPressed: () {
Navigator.pop(context);
},
height: 50.0,
minWidth: 50.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
child: Icon(
Icons.clear,
color: Colors.black54,
),
),
),
],
);
}
buildSecurityText() {
return Column(
children: [
Align(
alignment: Alignment.topLeft,
child: Text(
'Enter PIN',
style: TextStyle(
color: Color(0xff151515),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(
height: 12,
),
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(right: 80),
child: Text(
'Enter 4 digit PIN to access your account ',
style: TextStyle(
color: Color(0xff151515),
fontSize: 14,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal,
),
),
),
),
],
);
}
buildPinRow() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PINNumber(
outlineInputBorder: outlineInputBorder,
textEditingController: pinOneController,
),
PINNumber(
outlineInputBorder: outlineInputBorder,
textEditingController: pinTwoController,
),
PINNumber(
outlineInputBorder: outlineInputBorder,
textEditingController: pinThreeController,
),
PINNumber(
outlineInputBorder: outlineInputBorder,
textEditingController: pinFourController,
),
],
);
}
}
THIS IS MY CUSTOMIZED WIDGET TREE/CODE

Error on my UI using SingleChildScrollView when i try to run my firebase?

this is my first time using community to ask about my project. First thing first, english isn't my first language and I'm a very beginner in flutter world. I'm trying to build my first mobile application using flutter and now I'm trying to connect my project to firebase (I looked at youtube tutorial). I don't know if the firebase already connect because when I'm trying to run the application and go to registration page, there this error message.
And here is my code:
import 'package:dfu_check_application/common/auth_controller.dart';
import 'package:flutter/material.dart';
import 'package:dfu_check_application/common/theme_helper.dart';
import 'package:dfu_check_application/pages/widgets/header_widget.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'profile_page.dart';
class RegistrationPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _RegistrationPageState();
}
}
class _RegistrationPageState extends State<RegistrationPage> {
final _formKey = GlobalKey<FormState>();
bool checkedValue = false;
bool checkboxValue = false;
#override
Widget build(BuildContext context) {
var nameController = TextEditingController();
var emailController = TextEditingController();
var passwordController = TextEditingController();
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Stack(children: [
Container(
height: 150,
child: HeaderWidget(150, false, Icons.person_add_alt_1_rounded),
),
Container(
margin: EdgeInsets.fromLTRB(25, 50, 25, 10),
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
alignment: Alignment.center,
child: Column(
children: [
Form(
key: _formKey,
child: Column(
children: [
GestureDetector(
child: Stack(
children: [
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
border:
Border.all(width: 5, color: Colors.white),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 20,
offset: const Offset(5, 5),
),
],
),
child: Icon(
Icons.person,
color: Colors.grey.shade300,
size: 80.0,
),
),
Container(
padding: EdgeInsets.fromLTRB(80, 80, 0, 0),
child: Icon(
Icons.add_circle,
color: Colors.grey.shade700,
size: 25.0,
),
),
],
),
),
SizedBox(
height: 30,
),
Container(
child: TextFormField(
controller: nameController,
decoration: ThemeHelper().textInputDecoration(
'Full Name', 'Enter your full name'),
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(
height: 30,
),
SizedBox(height: 20.0),
Container(
child: TextFormField(
controller: emailController,
decoration: ThemeHelper().textInputDecoration(
"E-mail address", "Enter your email"),
keyboardType: TextInputType.emailAddress,
validator: (val) {
// ignore: prefer_is_not_empty
if (!(val!.isEmpty) &&
!RegExp(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)*$")
.hasMatch(val)) {
return "Enter a valid email address";
}
return null;
},
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(height: 20.0),
Container(
child: TextFormField(
obscureText: true,
controller: passwordController,
decoration: ThemeHelper().textInputDecoration(
"Password*", "Enter your password"),
validator: (val) {
if (val!.isEmpty) {
return "Please enter your password";
}
return null;
},
),
decoration: ThemeHelper().inputBoxDecorationShaddow(),
),
SizedBox(height: 15.0),
FormField<bool>(
builder: (state) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
Checkbox(
value: checkboxValue,
onChanged: (value) {
setState(() {
checkboxValue = value!;
state.didChange(value);
});
}),
Text(
"I accept all terms and conditions.",
style: TextStyle(color: Colors.grey),
),
],
),
Container(
alignment: Alignment.centerLeft,
child: Text(
state.errorText ?? '',
textAlign: TextAlign.left,
style: TextStyle(
color: Theme.of(context).errorColor,
fontSize: 12,
),
),
)
],
);
},
validator: (value) {
if (!checkboxValue) {
return 'You need to accept terms and conditions';
} else {
return null;
}
},
),
SizedBox(height: 20.0),
GestureDetector(
onTap: () {
AuthController.instance.register(
nameController.text.trim(),
emailController.text.trim(),
passwordController.text.trim());
},
),
Container(
decoration: ThemeHelper().buttonBoxDecoration(context),
child: ElevatedButton(
style: ThemeHelper().buttonStyle(),
child: Padding(
padding: const EdgeInsets.fromLTRB(40, 10, 40, 10),
child: Text(
"Register".toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
onPressed: () {
if (_formKey.currentState!.validate()) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => ProfilePage()),
(Route<dynamic> route) => false);
}
},
),
),
SizedBox(height: 30.0),
Text(
"Or create account using social media",
style: TextStyle(color: Colors.grey),
),
SizedBox(height: 25.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
child: FaIcon(
FontAwesomeIcons.google,
size: 35,
color: HexColor("#EC2D2F"),
),
onTap: () {
setState(() {
showDialog(
context: context,
builder: (BuildContext context) {
return ThemeHelper().alartDialog(
"Google Account",
"You tap on Google icon.",
context);
},
);
});
},
),
],
),
],
),
),
],
),
),
]),
),
);
}
}
If you guys see more error on my code, please tell me because I'm very clueless about this. Thank you in advance!
The issue occurs from Stack the one inside
Column(
children: [
Form(
key: _formKey,
child: Column(
children: [
GestureDetector(
child: Stack( // this one
Can be fixed by providing hight
GestureDetector(
child: SizedBox(
height: MediaQuery.of(context).size.height, //this based on your need
child: Stack(
I think you can re struct the widget and don't need to use multi-Stack.
More about /ui/layout and Unbounded height / width

Flutter getX not updating UI after ading items to obs list

I'm using GetX to manage the state of my ecommerce app, and I'm stuck with the shopping cart.
I'm using Sqflite package to store carts locally.
issue: when i add a product to cart list it's not updating it automatically untill i restart the app i see the added items
Cart controller
addProductToCart(ProductModel product) async {
List<Map> items =
await _repository.getLocalByCondition('carts', 'productId', product.id);
if (items.length > 0) {
product.quantity = items.first['productQuantity'] + 1;
return await _repository.updateLocal(
'carts', 'productId', product.toMap());
}
product.quantity = 1;
return await _repository.saveLocal('carts', product.toMap());
}
#override
void onInit() {
super.onInit();
getCarts();
}
Add to cart product details
_addToCart(BuildContext context, ProductModel product) async {
int result = await _cartController.addProductToCart(product);
if (result > 0) {
Fluttertoast.showToast(msg: 'Item added to cart successfully!');
} else {
Fluttertoast.showToast(msg: 'Error to add product!');
}
}
Cart screen
Obx(() {
return Scaffold(
appBar: AppBar(
title: Text('Cart (${_cartController.cartList.length} items)',
style: TextStyle(color: Colors.black))),
bottomNavigationBar: InkWell(
onTap: () {
//_checkout(_cartController.cartList);
},
child: Container(
color: Colors.black,
height: 55,
margin: EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Checkout',
style: TextStyle(color: Colors.white),
),
SizedBox(
width: 10,
),
Text(
'£' + _cartController.total.toString(),
style: TextStyle(color: Colors.white),
)
],
),
)),
body: _cartController.loading.isTrue
? Center(child: CircularProgressIndicator())
: _cartController.cartList.length > 0
? ListView.builder(
padding:
EdgeInsets.symmetric(horizontal: 8, vertical: 12),
itemBuilder: (context, index) {
return Dismissible(
key: Key(this
._cartController
.cartList[index]
.id
.toString()),
onDismissed: (val) async {
var x= await _cartController.deleteCartItem(
index, this._cartController.cartList[index].id);
if(x!>0) Fluttertoast.showToast(msg: 'deleted');
else{ Fluttertoast.showToast(msg: x.toString());
}
},
background: Container(
child: Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 28.0),
child: Icon(
Icons.delete_outline_outlined,
size: 36,
color: Colors.white,
),
)),
color: Colors.redAccent),
child: Card(
elevation: 5,
shape: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(7),
)),
child: Container(
margin: EdgeInsets.all(4),
height: 120,
child: Row(
children: [
Expanded(
flex: 3,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(5),
topRight: Radius.circular(5)),
child: Image.network(
_cartController.cartList[index].photo,
width: 150,
height: 120,
fit: BoxFit.cover,
),
),
),
Expanded(
flex: 5,
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
_cartController
.cartList[index].name,
overflow: TextOverflow.clip,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'${_cartController.cartList[index].price - _cartController.cartList[index].discount} ' +
" x " +
_cartController
.cartList[index].quantity
.toString(),
style: TextStyle(
fontWeight: FontWeight.w500),
),
),
],
)),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
IconButton(
icon: Icon(Icons.keyboard_arrow_up),
onPressed: () {
_cartController.total.value += this
._cartController
.cartList[index]
.price -
this
._cartController
.cartList[index]
.discount;
this
._cartController
.cartList[index]
.quantity++;
},
),
Text(_cartController
.cartList[index].quantity
.toString()),
IconButton(
icon: Icon(Icons.keyboard_arrow_down),
onPressed: () {
if (_cartController
.cartList[index].quantity >
1) {
_cartController.total.value -= (this
._cartController
.cartList[index]
.price -
this
._cartController
.cartList[index]
.discount);
this
._cartController
.cartList[index]
.quantity--;
}
},
),
],
))
],
),
),
),
);
},
itemCount: _cartController.cartList.length,
)
: Center(
child: Text('Your Shopping cart is empty'),
));
});
You need to add product in _cartController.cartList.
_addToCart(BuildContext context, ProductModel product) async {
cartList.add(product);
....
}

how to reduce the gap between this widgets? I tried tweaking padding values but no luck so far. Please take a look

This is the code
I tweaked the paading but no luck. I am new to flutter manage to build this but stuck, any suggestions/help is much appreciated!
import 'package:bmi_app_one/utils/TextStyle_Decorations.dart';
import 'package:bmi_app_one/utils/hexcolor.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class home_screen extends StatefulWidget {
#override
_home_screenState createState() => _home_screenState();
}
class _home_screenState extends State<home_screen> {
Color _appBar_bg_color = HexColor('#1C1C1E');
Color _app_bg_color = HexColor('#2c2c2e');
bool changeButtonColorMale = false;
bool changeButtonColorFemale = false;
int age = 20;
int weight = 30;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: homeScreenAppBarText,
backgroundColor: _appBar_bg_color,
centerTitle: true,
),
backgroundColor: _app_bg_color,
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: ScreenUtil().screenWidth,
height: 0.6.sh,
child: Row(
/* Entry Point of 1st set */
children: [
/* This contains both Male and female gender button */
Column(
children: [
Row(
children: [
/* Male Button */
Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 4, 8),
child: InkWell(
onTap: (){
debugPrint("Gender: Male pressed");
setState(() {
if(changeButtonColorMale == false){
changeButtonColorMale = true;
changeButtonColorFemale = false;
}
else{
changeButtonColorMale = false;
}
});
},
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
child: Container(
width: 0.4.sw,
height: 0.2.sh,
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(8.0)
),
margin: EdgeInsets.all(10),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Icon(Ionicons.ios_male,size: 88.ssp,
color: changeButtonColorMale ? Colors.yellow.withOpacity(0.7) : Colors.white),
),
Text(
"Male", style: TextStyle(
fontSize: 24.ssp,
fontFamily: 'San francisco',
color: changeButtonColorMale ? Colors.yellow.withOpacity(0.7) : Colors.white
),
),
],
),
),
),
),
/* Age */
Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
child: Container(
width: 0.43.sw,
height: 0.2.sh,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(8.0)
),
child: Column(
children: [
/* Age Text */
Padding(
padding: const EdgeInsets.fromLTRB(8, 36, 8, 8),
child: Text("AGE",
style: TextStyle(
fontSize: 24.ssp,
fontFamily: 'San francisco',
color: Colors.white
),
),
),
Row(
children: [
/* Age decrease icon */
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: IconButton(
icon: new Icon(
MaterialCommunityIcons.minus_circle_outline,
size: 42.ssp,
color: Colors.white,),
onPressed: (){
debugPrint("Age decreased by 1");
setState(() {
if(age <= 5){
}
else{
age --;
}
});
},
splashRadius: 0.1,
),
),
/* Display Age in numbers */
Padding(
padding: const EdgeInsets.fromLTRB(15, 8 , 0, 0),
child: Text(age.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 26.ssp,
fontFamily: 'San francisco',
),
),
),
/* Age increase icon */
Padding(
padding: const EdgeInsets.fromLTRB(3, 0, 0, 0),
child: IconButton(
icon: new Icon(
MaterialCommunityIcons.plus_circle_outline,
size: 42.ssp,
color: Colors.white,),
onPressed: (){
debugPrint("Age increased by 1");
setState(() {
if(age >= 90){
}
else{
age ++;
}
});
},
splashRadius: 0.1,
),
)
],
)
],
),
),
)
],
),
Row(
children: [
/* Female Button */
Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 4, 0),
child: new InkWell(
onTap: (){
debugPrint("Gender: Female pressed");
setState(() {
if(changeButtonColorFemale == false){
changeButtonColorFemale = true;
changeButtonColorMale = false;
}
else{
changeButtonColorFemale = false;
}
});
},
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
child: Container(
width: 0.4.sw,
height: 0.2.sh,
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(8.0)
),
margin: EdgeInsets.all(10.0),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Icon(Ionicons.ios_female,size: 88.ssp,
color: changeButtonColorFemale ? Colors.yellow.withOpacity(0.7) : Colors.white),
),
Text(
"Female", style: TextStyle(
fontSize: 24.ssp,
fontFamily: 'San francisco',
color: changeButtonColorFemale ? Colors.yellow.withOpacity(0.7) : Colors.white
),
),
],
),
),
),
),
/* Weight */
Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
child: Container(
width: 0.43.sw,
height: 0.2.sh,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(8.0)
),
child: Column(
children: [
/* Weight Text */
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(24, 36, 3, 8),
child: Text("WEIGHT",
style: TextStyle(
fontSize: 24.ssp,
fontFamily: 'San francisco',
color: Colors.white
),
),
),
Text("(Kg)",
style: TextStyle(
color: Colors.white.withOpacity(0.7),
fontSize: 11.ssp,
fontFamily: 'San francisco',
),
),
],
),
Row(
children: [
/* Weight decrease icon */
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: IconButton(
icon: new Icon(
MaterialCommunityIcons.minus_circle_outline,
size: 42.ssp,
color: Colors.white,),
onPressed: (){
debugPrint("Weight decreased by 1");
setState(() {
if(weight <= 5){
}
else{
weight --;
}
});
},
splashRadius: 0.1,
),
),
/* Display Weight in numbers */
Padding(
padding: const EdgeInsets.fromLTRB(15, 8 , 0, 0),
child: Text(weight.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 26.ssp,
fontFamily: 'San francisco',
),
),
),
/* Weight increase icon */
Padding(
padding: const EdgeInsets.fromLTRB(3, 0, 0, 0),
child: IconButton(
icon: new Icon(
MaterialCommunityIcons.plus_circle_outline,
size: 42.ssp,
color: Colors.white,),
onPressed: (){
debugPrint("Weight increased by 1");
setState(() {
if(weight >= 625){
}
else{
weight ++;
}
});
},
splashRadius: 0.1,
),
)
],
)
],
),
),
),
],
)
],
),
],
),
),
/* Height Slider 2nd set */
Container(
width: ScreenUtil().screenWidth,
height: 0.15.sh,
decoration: BoxDecoration(
color: Colors.white
),
child: Column(
children: [],
),
)
],
),
)
);
}
}
This is the screenshot at present
tweaked the paading but no luck. I am new to flutter manage to build this but stuck, any suggestions/help is much appreciated!
You're creating that extra space with how you're setting the height of the 2nd Container at the top of your build method. I assume that the sh in height: 0.6.sh, is ScreenHeight * 0.6?
It doesn't appear that either of those first 2 Container's are adding anything of value. You can just remove them both and your white Container at the bottom should jump up closer to everything else.

Flutter : serState() or markNeedBuild() called during build

I have a widget which used to select a date, at beginning it's with 'no date chosen', and the widget in a column below it depends on it [which mean its show a list of timeSlots of Data if I selected a date]
But I got a setState called during build error, and This ReservationSlotWidget can not be marked as needing to build because the Framework is already in the process of building widgets
This is the selectDate widget
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Icon(
Icons.date_range,
color: Colors.white,
),
SizedBox(
width: 5,
),
Text(
_formatted == null
? 'No date chosen'
: _formatted,
style: TextStyle(
color: Colors.white,
))
],
),
FlatButton(
onPressed: ()=>_selectReservationDate(context),
child: Text(
'choose Date',
style: TextStyle(
color: Colors.white,
decoration: TextDecoration.underline),
),
)
],
),
if(_selectedDate != null)
Divider(
color: parseColor('#2A2E43'),
thickness: 2.0,
),
if(_selectedDate != null)
Row(
children: <Widget>[
Icon(
Icons.alarm,
color: Colors.white,
),
SizedBox(
width: 5,
),
Text('$_numberOfSeats Available Time Slots',
style: TextStyle(
color: Colors.white,
))
],
),
this is a listview items which appeared depend on the date I chose.
if(_formatted != null)
Expanded(
child: Consumer<SlotProvider>(
builder: (ctx, slotProvider, _)=>
ListView.builder(
itemCount: slotProvider.slots.length,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, index) {
setState(() {
_numberOfSeats = slotProvider.slots[index].seats;
});
return GestureDetector(
onTap: () {
setState(() {
if(_isInit){
_isExpanded = !_isExpanded;
}
_expandedIndex = index;
_isInit = false;
});
},
child: Container(
padding: EdgeInsets.all(4),
margin: EdgeInsets.all(4),
decoration: BoxDecoration(
color: _expandedIndex == index
? Theme.of(context).primaryColor
: parseColor('#2A2E43'),
borderRadius:
BorderRadius.all(Radius.circular(10))),
child: SlotsWidget(
fromTime: slotProvider.slots[index].fromTime.toString(),
toTime:slotProvider.slots[index].toTime.toString(),
seats:slotProvider.slots[index].seats,
))
);
}
),
)
),
the comment of #void is right and you can avoid the repeated setState with if block;
if (_numberOfSeats != slotProvider.slots[index].seats)
setState(() {
_numberOfSeats = slotProvider.slots[index].seats;
});