Issue with Login form Layout in Flutter - flutter

I'm making a login form in Flutter, I'm using a ListView that has a Container as a child and it's child is a Stack widget which has Positioned children. Because of the Stack, I have to have a bound height, so hence the Container widget, which I gave the height: height: MediaQuery.of(context).size.height * 1.2. If I remove the * 1.2 my Button and and Text widget don't show up, and when I click on the login with * 1.2, my validator pops up, red warning signs shows that your info is entered incorrectly, so I can't see the button anymore. Example in pictures:
This is with height: MediaQuery.of(context).size.height * 1.2
Then I try to login, validator pops, and now I can't see the button nor the text and link below the button:
The problem I am facing is, how do I layout this login form that can only be scrollable as far as it needs, so I don't have empty space after the Button, just to spread the form so it is visible, not get something like this if I increment the height of the Container?
Code:
ListView(
shrinkWrap: true,
children: [
Container(
height: MediaQuery.of(context).size.height * 1.6,
child: Stack(
children: [
Positioned(
width: MediaQuery.of(context).size.width,
top: MediaQuery.of(context).size.width * 0.1,
child: Image.asset(
'assests/images/loginform.png',
scale: 2.5,
height: 60,
width: 119,
),
),
Positioned(
width: MediaQuery.of(context).size.width,
top: MediaQuery.of(context).size.width * 0.35,
child: Padding(
padding: const EdgeInsets.only(left: 24.0, right: 25.0),
child: Column(
children: <Widget>[
Form(
key: _registrationFormKey,
child: Column(
children: [
TextFormField(
textAlign: TextAlign.start,
onChanged: (value) {
context.read<User>().name = value;
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Full name'),
validator: (thisValue) {
if (thisValue.isEmpty) {
return 'Please enter your full name';
}
return null;
},
),
SizedBox(
height: 24.0,
),
TextFormField(
keyboardType: TextInputType.phone,
textAlign: TextAlign.start,
onChanged: (value) {
context.read<User>().phoneNumber = value;
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Phone number'),
validator: _validateMobile,
),
SizedBox(
height: 24.0,
),
TextFormField(
keyboardType: TextInputType.streetAddress,
textAlign: TextAlign.start,
onChanged: (value) {
context.read<User>().address = value;
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Address'),
validator: (thisValue) {
if (thisValue.isEmpty) {
return 'Please enter your address';
}
return null;
},
),
SizedBox(
height: 24.0,
),
TextFormField(
keyboardType: TextInputType.text,
textAlign: TextAlign.start,
onChanged: (value) {
context.read<User>().companyName = value;
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Company name'),
validator: (thisValue) {
if (thisValue.isEmpty) {
return 'Please enter your company name';
}
return null;
},
),
SizedBox(
height: 24.0,
),
TextFormField(
keyboardType: TextInputType.text,
textAlign: TextAlign.start,
onChanged: (value) {
context.read<User>().website = value;
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Website name'),
validator: _validateWebsite),
SizedBox(
height: 24.0,
),
TextFormField(
keyboardType: TextInputType.emailAddress,
textAlign: TextAlign.start,
onChanged: (value) {
context.read<User>().email = value;
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'E-mail address'),
validator: _validateEmail,
),
SizedBox(
height: 24.0,
),
TextFormField(
keyboardType: TextInputType.text,
obscureText: _obscureText,
textAlign: TextAlign.start,
onChanged: (value) {
context.read<User>().password = value;
},
decoration: kTextFieldDecoration.copyWith(
hintText: 'Password',
suffixIcon: IconButton(
icon: const Icon(Icons.visibility_outlined),
onPressed: _togglePassVisibility,
),
),
validator: _validatePassword,
),
],
),
),
FormField<bool>(
// 1
initialValue: _agree,
builder: (FormFieldState<bool> state) {
// 2
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Checkbox(
// 3
value: state.value,
onChanged: (bool val) => setState(() {
// 4
_agree = val;
// 5
state.didChange(val);
}),
),
const Text('I agree with'),
TextButton(
onPressed: () {},
child: Text('Terms and conditions'),
),
],
),
// 6
state.errorText == null
? Text("")
: Text(state.errorText,
style: TextStyle(color: Colors.red)),
],
);
},
// 7
validator: (val) => _validateTerms(_agree),
),
AlarmButtons(
buttonColour: Color(0xFF29ABE2),
buttonText: 'CREATE ACCOUNT',
buttonTextColour: Colors.white,
buttonBorderSide: Colors.white,
onButtonPress: () async {
if (_registrationFormKey.currentState.validate()) {
signUpToCognito(context);
Navigator.pushNamed(
context, ConfirmRegistrationScreen.id);
}
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Already have an account?'),
TextButton(
onPressed: () {
Navigator.pushNamed(context, LoginScreen.id);
},
child: Text('Log in'),
),
],
),
],
),
),
),
],
),
)
],
)
Thanks in advance for the help and suggestions!

there are a couple mistakes (or at least optimizations) in your code. I will go over them one by one:
If you have a small number of children that need to be scrolled, it is better to use a SingleChildScrollView with a Column instead of a list view. ListView builds its children lazily - that is, it only builds widgets that are visible on the screen. If you have only a handful of widgets with no complex animations, then you don't really need that. SingleChildScrollView is more flexible that a ListView.
SingleChildScrollView(
child: Column(
children: [...]
)
)
It seems that you want the image to be on the background with the form validation on top of it. For that, you used a Stack and a Column as children to a ListView. Instead, have the Stack as a parent, with both the ListView and the image as children to the Stack. Now this might produce an error, as the ListView might expand infinitely. A simple solution is to wrap it within a Positioned widget with all its sides set to zero.
Stack(
children: [
BackgroundImageWidget(),
Positioned(
top: 0, bottom: 0, left: 0, right: 0, // or width: screenWidth, height: screenHeight,
child: ListView(...),
)
]
)

Related

flutter text field underline and dropdown underline are not in the same line

hi, in flutter I have tow widgets TextFormField and DropdownButton in a Row But as you see in the picture they are not in the same line
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
SizedBox(
width: HDW().fullWidth(context: context, width: 0.35),
height: HDW().fullHeight(context: context, height: 0.08),
child: TextFormField(
controller: sectionTextEditingController,
onChanged: (n) {
homeController.setSectionNo(n);
},
keyboardType: TextInputType.number,
),
),
SizedBox(
width: HDW().fullWidth(context: context, width: 0.35),
height: HDW().fullHeight(context: context, height: 0.08),
child:
DropdownButton<String?>(
items: homeController.sections
.map((e) => DropdownMenuItem<String?>(
value: e,
child: Text( e,textAlign: TextAlign.start,style: TextStyle(fontFamily: font),),
),)
.toList(),
value: homeController.selectedLetter.isNotEmpty
? homeController.selectedLetter
: null,
onChanged: (value) {
homeController.setSectionLetter(value!);
},
hint: Text(
'تحديد',
style: TextStyle(fontFamily: font),
),
isExpanded: true,
icon: const Icon(Icons.keyboard_arrow_down),
),
),
],
)
for note
double fullHeight({
required BuildContext context,
double height = 1,
}) =>
height * MediaQuery.of(context).size.height;
Setting isDense: true on DropdownButton will solve the bottom padding,
child: DropdownButton<String?>(
isDense: true,
but when it large size, textFiled is needed to be
child: TextFormField(
expands: true,
maxLines: null,
minLines: null,

flutter DropdownButtonFormField long item not fully displayed

when DropdownMenuItem is not fully displayed because of its height. so Im wonseringhow can I make the size change dynamically to fully display the chosen item
DropdownButtonFormField(
isExpanded: true,
validator: (value){
if(value== null){
return "Campo vuoto";
}
else {
return null;
}
},
decoration:InputDecoration(
labelText: "Locale",
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(5))
)
) ,
onChanged: (value) {
setState(() {
chosenService = value.toString();
});
},
items: locals.map((local) => DropdownMenuItem(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(local.name,style: TextStyle(fontSize: 14, color: Color(Helper.getColorByType(local.type)), fontWeight: FontWeight.w400),
overflow: TextOverflow.visible),
Text(Helper.getAdressFromDescription(local.description), style: TextStyle(fontSize: 12, color: Colors.black54),
overflow: TextOverflow.ellipsis)
],
),
),
value: local.type+' - '+local.name,
),
).toList(),
),
image1
image2
I think that it can help you
SizedBox(
height: 100//I use default value as well but you can another value or MediaQuery
width: MediaQuery.of(context).size.width / x.x, //try ideal values
child: DropdownButtonFormField(
...
decoration: const InputDecoration(
border: InputBorder.none, contentPadding: EdgeInsets.all(0), ),
alignment: Alignment.bottomCenter,
...
),

How do I align a TextFormField and Text widget inside a row in Flutter?

I am new to flutter, I would like to align the text widget shown in the screen shot to the bottom of the row so it is on the same line as the text form field. I would like to move "Kilos" to the bottom of the row.
Here is the code:
return Row(
children: [
Flexible(
child: TextFormField(
decoration: InputDecoration(labelText: label),
keyboardType: _getKeyboardType(),
validator: (value) => _getFormValidator()(value),
onSaved: (value) { saveAction(formItem,value); },
onTap: () {print(TextInputType.emailAddress);},
),
),
Text('Kilos',style: TextStyle(backgroundColor: Colors.red),)
],
);
I have tried wrapping the Row and the Text widgets within an Align widget.
You can achieve this with Stack..
here is sample code.
Stack(
children: [
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter a search term'
),
),
Positioned(
right: 0,
bottom: 0,
child: Text(
'Kilos',
style: TextStyle(backgroundColor: Colors.red),
))
],
),
You can try with intrinsic height and make your crossAlignment.end
IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: Align(
alignment: Alignment.topLeft,
child: TextFormField(
decoration: InputDecoration(labelText: "label"),
/* keyboardType: _getKeyboardType(),
validator: (value) => _getFormValidator()(value),
onSaved: (value) {
saveAction(formItem, value);
},*/
onTap: () {
print(TextInputType.emailAddress);
},
),
),
),
Text(
'Kilos',
style: TextStyle(backgroundColor: Colors.red),
)
],
),
)
Output:

here my listview is not scrolling dart flutter , please help me iam new to flutter

return Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Stack(
children: [
Positioned(
width: MediaQuery.of(context).size.width,
height: 25.0*SizeConfig.heightMultiplier,
child:Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xff009cba), Color(0xff000e11)])
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(flex:3,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
FittedBox(child: Text("Firm Details",style: GoogleFonts.lato(color: Color(0xfffbfbfb),fontSize: 1.6*SizeConfig.textMultiplier),/*TextStyle(color: Color(0xfffbfbfb),)*/)),
SizedBox(height: 0.5*SizeConfig.heightMultiplier,),
FittedBox(child: Text("Please select the category that best describes your business model.",style: GoogleFonts.lato(color: Color(0xffb3fbfbfb),fontSize: 1.3*SizeConfig.textMultiplier) /*TextStyle(color: Color(0xffb3fbfbfb),fontSize: 12.0)*/,)),
],
),
),
),
Expanded(flex:1,child:Container(
width: 10.0*SizeConfig.widthMultiplier,
height: 10.0*SizeConfig.heightMultiplier,
child:Image.asset("assets/images/firmDetail.png",width:1.0*SizeConfig.widthMultiplier,height: 1.0*SizeConfig.heightMultiplier,),
), ),
],
),
), ),
Positioned(
top:20.0*SizeConfig.heightMultiplier,
child:Container(
width: MediaQuery.of(context).size.width,
height: 500.0*SizeConfig.heightMultiplier,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0*SizeConfig.widthMultiplier),
color: Colors.white,
),
child:new Container(
child: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
SizedBox(height: 2.0*SizeConfig.heightMultiplier,),
Center(child: Padding(
padding: EdgeInsets.all(1.8*SizeConfig.heightMultiplier),
child: Text("Please select the category that best describes your business model.",style: GoogleFonts.lato(fontWeight: FontWeight.bold),),
)),
horizontalList1,
verticalList, // here vertical list
],
),
),
),
),
],
),
),
);
here in widget verticallist Listview is not scrolling,but when we add Sizedbox after form with fixedheight then it is scrolling but i dont need fixed height for scrollview
Widget verticalList = new Container(
margin: EdgeInsets.symmetric(vertical: 0*SizeConfig.heightMultiplier),
height: MediaQuery.of(context).size.height,
child:ListView(
shrinkWrap: true,
scrollDirection: Axis.vertical,
children: [
Form(
key: _formKey,
child:ListView(
shrinkWrap: true,
children: [
Padding(
padding:EdgeInsets.only(left:6.0*SizeConfig.widthMultiplier,right: 6.0*SizeConfig.widthMultiplier,top:1.8*SizeConfig.widthMultiplier,bottom: 1.8*SizeConfig.widthMultiplier),
child: new TextFormField(
validator: (String value) {
if (value.isEmpty) {
return 'PinCode';
} else {
return null;
}
},
keyboardType: TextInputType.phone,
controller: _pincode,
// selectionColor:Color(0xffe4065f),
style: GoogleFonts.lato(fontSize: 1.6*SizeConfig.textMultiplier,),
decoration: const InputDecoration(
labelText: "PinCode",
labelStyle: TextStyle(color: Color(0xffe4065f)),
focusColor: Color(0xffe4065f),
hintText:
"PinCode",
hintStyle: TextStyle(fontSize: 13.0),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Color(0xffe4065f))),
),
// style: Theme.of(context).textTheme.body1,
),
),
Padding(
padding:EdgeInsets.only(left:6.0*SizeConfig.widthMultiplier,right: 6.0*SizeConfig.widthMultiplier,top:1.8*SizeConfig.widthMultiplier,bottom: 1.8*SizeConfig.widthMultiplier),
child: new TextFormField(
validator: (String value) {
if (value.isEmpty) {
return 'PAN of the unit. is required';
} else {
return null;
}
},
keyboardType: TextInputType.text,
controller: _pan,
// selectionColor:Color(0xffe4065f),
style: GoogleFonts.lato(fontSize: 1.6*SizeConfig.textMultiplier,),
decoration: const InputDecoration(
labelText: "PAN of the unit",
labelStyle: TextStyle(color: Color(0xffe4065f)),
focusColor: Color(0xffe4065f),
hintText:
"PAN of the unit",
hintStyle: TextStyle(fontSize: 13.0),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Color(0xffe4065f))),
),
// style: Theme.of(context).textTheme.body1,
),
),
Padding(
padding:EdgeInsets.only(left:6.0*SizeConfig.widthMultiplier,right: 6.0*SizeConfig.widthMultiplier,top:1.8*SizeConfig.widthMultiplier,bottom: 1.8*SizeConfig.widthMultiplier),
child: FormField<String>(
builder: (FormFieldState<String> state) {
return InputDecorator(
decoration: InputDecoration(
labelText: "Constitution",
errorStyle: TextStyle(color: Colors.redAccent, fontSize: 1.6*SizeConfig.textMultiplier),
hintText: 'Please select expense',),
isEmpty: _constitutions == '',
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: _constitutions,
isDense: true,
onChanged: (String newValue) {
setState(() {
_constitutions = newValue;
state.didChange(newValue);
});
},
items: _constitution.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value,style: GoogleFonts.lato(fontSize: 1.6*SizeConfig.textMultiplier,)),
);
}).toList(),
),
),
);
},
),
),
Padding(
padding:EdgeInsets.only(left:6.0*SizeConfig.widthMultiplier,right: 6.0*SizeConfig.widthMultiplier,top:1.8*SizeConfig.widthMultiplier,bottom: 1.8*SizeConfig.widthMultiplier),
child: new TextFormField(
validator: (String value) {
if (value.isEmpty) {
return 'Line of Activity is required';
} else {
return null;
}
},
keyboardType: TextInputType.text,
controller: _lineActicity,
// selectionColor:Color(0xffe4065f),
style: GoogleFonts.lato(fontSize: 1.6*SizeConfig.textMultiplier,),
decoration: const InputDecoration(
labelText: "Line of Activity",
labelStyle: TextStyle(color: Color(0xffe4065f)),
focusColor: Color(0xffe4065f),
hintText:
"Line of Activity",
hintStyle: TextStyle(fontSize: 13.0),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Color(0xffe4065f))),
),
// style: Theme.of(context).textTheme.body1,
),
),
Padding(
padding:EdgeInsets.only(
left: 1.0*SizeConfig.widthMultiplier,
right: 1.0*SizeConfig.widthMultiplier,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FlatButton(
onPressed: () {
//x _postData();
if (!_formKey.currentState.validate()) {
//_formKey.currentState.save();
if (_constitutions == null || _districtSelectedValue == null) {
print("eroore");
Flushbar(
message: "please select required fields",
duration: Duration(seconds: 3),
)..show(context);
} else {
// Every of the data in the form are valid at this point
_formKey.currentState.save();
print(_constitutions);
}
} else {
// submitOtp();
_postData();
}
},
child: Text(
"SAVE & NEXT",
style: GoogleFonts.lato(color: Colors.white),
),
color: Color(0xffe4065f),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
side: BorderSide(color: Color(0xffe4065f)),
),
),
],
),
),
],
),
),
// SizedBox(height: 1000,),
],
)
);
here ,when we add Sizedbox after form with fixedheight then it is scrolling but i dont need fixed height for scrollview im new to flutter please help
You can wrap your main widget with the SingleChildScrollView widget
I would suggest a simple widget hierarchy like
Scaffold
- Container (For the red background)
- Column
- Container (with size for the lorem ipsom text.
- Lorem Ipso Text.
- Expanded (So that it will use the rest of the height automatically.)
- Container (with white back ground and top rounded borders. Makes sure you add circular borders only to top and not to bottom of this container.
- DefaultTabController
- builder (to get different context of the default tab controller if more than one is used in your full app.)
- Column
- TabBar (if the number of categories is large use scrolling here as a property of the tab bar.) wrap in container if you need specific height of the tab bar.
- Expanded
- TabBarView to show the appropriate form.
- SingleChildScrollView
-Column
-Your fields
your list view is wrapper in a container that is very long and has no scroll on it. So it wont scroll as the list fits within that long container.
With list views you want a fixed height. It is the fixed height that is given for the visible parts of the list. Remove the wrapping container or reduce the height so all of it is visible on screen.
Also look at your use of the stack. You might have issues once you fix this with the list scrolling on top of the text "Firm Details" etc.

Flutter: ListTile width

I have this code displaying 2 ListTiles in the same line:
Row(
children: <Widget>[
Flexible(
child: ListTile(
leading: Icon(Icons.call),
title: TextFormField(
controller: _phoneNumberController,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
hintText: translate('contact_list.number')),
validator: (value) {
return Helpers.checkInput(value);
},
),
),
),
Expanded(
child: ListTile(
title: TextFormField(
controller: _phoneNumberController,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
hintText: translate('contact_list.number')),
validator: (value) {
return Helpers.checkInput(value);
},
),
),
),
],
),
Both of them are taking 50% of the space but I'd need the first one taking a fixed width.
What I'm trying to archive is display a telephone number input with its phone code on the left (and that needs to be smaller)
This could be a possible solution for what you are looking for:
Row(
children: <Widget>[
ConstrainedBox(
constraints: BoxConstraints(
/// Just an example, but this makes sure, that since you set a fixed width like 300.0, on small screens this won't get too big. For example by setting a maxWidth constraint like this, its width will be 300.0, but at max as big as 1 / 3 of the screen width so it gets smaller on small screen sizes
maxWidth: MediaQuery.of(context).size.width / 3,
),
child: SizedBox(
/// Enter your fixed width here, 300.0 ist just an example
width: 300.0,
child: ListTile(
leading: Icon(Icons.call),
title: TextFormField(
controller: _phoneNumberController,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
hintText: translate('contact_list.number')),
validator: (value) {
return Helpers.checkInput(value);
},
),
),
),
),
Expanded(
child: ListTile(
title: TextFormField(
controller: _phoneNumberController,
keyboardType: TextInputType.phone,
decoration: InputDecoration(
hintText: translate('contact_list.number')),
validator: (value) {
return Helpers.checkInput(value);
},
),
),
),
],
),