Related
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:
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(...),
)
]
)
I have TextFormField and I increased height of this field. I would like to start text from the left top corner and make that text will break at the end of the line. So if someone will put a lot of text, field will have X lines not only one.
How it looks now:
How it should looks like
Code:
TextFormField(
controller: contentController,
decoration: InputDecoration(
contentPadding: new EdgeInsets.symmetric(
vertical: MediaQuery.of(context).size.height * .10,
horizontal: 10.0),
border: OutlineInputBorder(),
hintText: 'Treść',
fillColor: Color(0xffffffff),
filled: true,
prefixIcon: Icon(Icons.topic_rounded),
),
validator: (value) {
if (value == null || value.isEmpty) {
return ErrorMessages.NO_CONTENT_MESSAGE;
}
},
),
There are a few things you can do:
You can add maxLines: desiredNumberOfLines and textAlignVertical: TextAlignVertical.top, to your TextFormField and wrap your prefix icon with Padding like this:
TextFormField(
textAlignVertical: TextAlignVertical.top,
decoration: InputDecoration(
prefixIcon: Padding(
padding: const EdgeInsets.only(bottom: 70.0),
child: Icon(
Icons.topic_rounded,
),
),
...
),
maxLines: 5,
...
),
You can wrap your TextFormField with a SizedBox widget and add expands: true to the text field, also you have to set minLines and minLines to null, because otherwise you get an error. The icon alignment can be the same as in the previous example with wrapping the icon with a Padding widget or you can do it the other way, which is shown in this example. It is done by using a prefix parameter instead of prefixIcon like this:
SizedBox(
height: 200,
child: TextFormField(
textAlignVertical: TextAlignVertical.top,
expands: true,
maxLines: null,
minLines: null,
decoration: InputDecoration(
prefix: Icon(
Icons.topic_rounded,
),
...
),
...
),
)
Choose a combination of text and icon alignment methods that works best for you.
You need to specify the height of your prefix icon by default it will be in the center. But to make it go on top you need to add Container() in which you will add your icon like this.
TextFormField(
minLines: 4,
keyboardType: TextInputType.multiline,
maxLines: 4,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Treść',
fillColor: Color(0xffffffff),
filled: true,
prefixIcon: Container(
width: 20,
height: 100,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.topic_rounded),
),
Container(),
],
),
),
prefixIconConstraints: BoxConstraints(
minWidth: 35,
minHeight: 0,
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return "error";
}
return null;
},
)
It will look like this
I'm new to flutter, and right now I'm trying to do something similar to this:
img 1.
Where the textformfield is aligned inline with the checkbox, and the checkbox is shrunk at the corner, but the max that I can do is this:
img 2.
Where the checkbox is filling half of the screen, I've tried to expand the textformfield in several ways, like sizedbox, flex and expand, but none of then made the checkbox shrink to the corner and the textformfield expand, the line is always split in the middle.
The actual row code looks like this:
Row(
children: [
Expanded(
child: TextFormField(
style: TextStyle(
fontSize: 20
),
decoration: InputDecoration(
hintText: "Senha",
),
autocorrect: false,
obscureText: true,
),
),
Flexible(
child: SizedBox(
width: 10,
child: Checkbox(value: true, onChanged: (value){}),
)
)
],
),
Is there any way for me to do this?
Do I have to use a container or something like that?
Any help would be appreciated.
You can use CheckboxListTile class.
CheckboxListTile(
title: const Text('Title'),
value: value,
onChanged: (value) {
print(value);
},
);
let me know if it work for you.
I've managed to do it using flex property, as the following code shows:
Row(
children: [
Expanded(
flex: 11,
child: TextFormField(
style: TextStyle(
fontSize: 20
),
decoration: InputDecoration(
hintText: "Usuario",
),
autocorrect: false,
obscureText: true,
),
),
Flexible(
child: SizedBox(
width: 10,
child: CheckboxListTile(
value: true,
onChanged: (value) {
},
),
)
)
],
),
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.