How to position two widget in a same Row? - flutter

I have a Country code(DropdownMenu) and phone (TextFormField), how can I put them in same level?
I've tried Align widget.
Row(
children: <Widget>[
Flexible(
flex: 1,
child: DropdownButtonFormField(
value: _selectedCountryCode ?? 'TR',
onChanged: (value) {
setState(() {
_selectedCountryCode = value;
});
},
items: countryCodes,
),
),
Flexible(
flex: 4,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: TextFormField(
decoration: InputDecoration(labelText: "Phone"),
),
),
),
],
),

Thanks to #danish-khan-I, I solved using crossAxisAlignment: CrossAxisAlignment.baseline. But you also have to provide textBaseline otherwise it gives an exception.
So in my row I've used:
crossAxisAlignment: CrossAxisAlignment.baseline
textBaseline: TextBaseline.ideographic,

Related

flutter box constraints not propagating to child as expected

I have learned that to make a Text wrap, you have to wrap it inside a Flexible() and set softWrap: true.
I have a ListView() with items generated by the following code:
return Container(
constraints: const BoxConstraints(maxWidth: 300),
child: Row(mainAxisSize: MainAxisSize.min, children: [
Checkbox(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap),
GestureDetector(
onTap: () {},
child: Container(
color: Colors.white,
child: Row(mainAxisSize: MainAxisSize.min, children: [
Icon(getCustomIcon(name: f.icon), size: 20, color: Colors.black),
const SizedBox(width: 6),
Flexible(
child: Text(f.name,
softWrap: true, style: TextStyle(fontSize: 14))),
const SizedBox(width: 6),
]),
))
]),
);
The Container should have a maximum width of 300 (see the outer BoxConstraints), but the innermost Text() node does not wrap and overflows.
Somewhere in here the box constraints get lost, but I don't understand where.
Note: I removed UI non-relevant code like onTap/onChange/...
After some more testing around I was able to solve the problem myself.
The problem is wrapping a row inside a row (even with other containers in-between) removes the constraints.
The solution is to put a Flexible/Expanded as the child of the parent row:
// innerRow is unconstrained
Row( children: [
...otherElements,
Row() // innerRow
]);
// innerRow is constrained
Row( children: [
...otherElements,
Flexible( // Flexible or Expanded tells the child to fill in the remaining space.
child: Row() // innerRow
)
]);
try :
Wrap your Container with either Row() or Center().
here is Code :
return Center(
child: Container(
constraints: const BoxConstraints(maxWidth: 300),
child: Row(mainAxisSize: MainAxisSize.min, children: [
Checkbox(
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
onChanged: (bool? value) {},
value: true,
),
GestureDetector(
onTap: () {},
child: Container(
color: Colors.white,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.abc,
size: 20, color: Colors.black),
const SizedBox(width: 6),
Flexible(
child: Text("f.name",
softWrap: true,
style: TextStyle(fontSize: 14))),
const SizedBox(width: 6),
]),
))
]),
),
);

How to build a flutter form with two columns and multiple rows?

I am trying to build a rather simple Flutter form that consists of three rows of which the first two rows each hold three columns. I therefore made a Form that holds a Padding as a child, while this Padding has a Column as a child, which finally contains the three rows:
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Please enter place of departure';
}
return null;
},
controller: fromController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'From'
),
),
RaisedButton(
onPressed: () => _selectDate(context),
child: Text('Select date'),
),
RaisedButton(
onPressed: () => _selectTime(context),
child: Text('Select time'),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Please enter destination';
}
return null;
},
controller: toController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'To'
),
)
]
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
onPressed: () {
// Validate returns true if the form is valid, or false
// otherwise.
if (_formKey.currentState.validate()) {
// If the form is valid, display a Snackbar.
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('You fly from '+fromController.text+' to '+toController.text)));
}
},
child: Text('Take off'),
),
]
),
],
),
),
);
}
Unfortunately this is not working this way and I can't figure out, how I need to structure the Form to build it successfully and leads to a render error. What I would like to build in the end would be something like this:
While wrapping rows into column there should be size specified, You can wrap your rows && children's with Flexible or Expanded, this worked for your example:
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Flexible(
child: TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Please enter place of departure';
}
return null;
},
controller: fromController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'From'
),
),
),
Flexible(
child: RaisedButton(
onPressed: () => _selectDate(context),
child: Text('Select date'),
),
),
Flexible(
child: RaisedButton(
onPressed: () => _selectTime(context),
child: Text('Select time'),
),
),
],
),
),
Flexible(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Flexible(
child: TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Please enter destination';
}
return null;
},
controller: toController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'To'
),
),
)
]
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
onPressed: () {
// Validate returns true if the form is valid, or false
// otherwise.
if (_formKey.currentState.validate()) {
// If the form is valid, display a Snackbar.
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('You fly from '+fromController.text+' to '+toController.text)));
}
},
child: Text('Take off'),
),
]
),
],
),
),
);
}
You might specify flex, work with expanded instead of flexibles & try some other mainAxisAlignment behaviours on your rows for the best effect, but in general it works pretty good

How to give a constant width to a Flutter DropdownButton widget?

How can I give a constant width to a DropDownButton in a Flutter?
As I got to know why they both DropDownButton as different width size in below image,
as 1st one as the highest length of value "100%" in it & the
2nd one as highest value as "90%" in it, so there is a difference in the length of the string so it wrapping accordingly.
I want to give a fixed width for them so that they look the same.
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(title,
style: Theme.textTheme.body1
.copyWith(fontWeight: ThemeData.medium)),
DropdownButton(
disabledHint: Text(defaultValue),
value: currentDropDownItem,
items: dropDownItemList,
onChanged: isEnabled
? (value) {
if (onValueChanged != null) {
onValueChanged(value);
}
}
: null,
),
])
Wrap it inside a Container or SizedBox with width as,
new Container(
width: 75.0,
child: //your DropdownButton here
),
or you can use Expanded inside a Row,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 5,
child: Text(
title,
style: Theme.textTheme.body1
.copyWith(fontWeight: ThemeData.medium),
),
),
Expanded(
flex: 1,
child: DropdownButton(
disabledHint: Text(defaultValue),
value: currentDropDownItem,
items: dropDownItemList,
onChanged: isEnabled
? (value) {
if (onValueChanged != null) {
onValueChanged(value);
}
}
: null,
),
),
],
),
Hope it might be helpful.

How to align buttom TextField by top TextField?

I need to align bottom input field by top input field. Like:
Here is my code:
class CustomerInput extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: TextField(),
),
RaisedButton(
child: Icon(Icons.search),
onPressed: () {},
),
],
// ),
),
TextField(
enabled: false,
)
],
);
}
}
How to do it?
Following code will give exact view as you need. In second raw you will add only one TextFormField/TextField for edittext/textview.
Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
flex: 3,
child: TextFormField(
),
),
Expanded(
flex: 1,
child: RaisedButton(
child: Icon(Icons.search),
onPressed: () {},
),
),
],
// ),
),
Row(
children: <Widget>[
Expanded(
child: TextFormField(
),
)
],
)
],
));
in this code flex property of TextField is 3 and RaisedButton is 1
"sum equality of these is 4"
TextField will expand by 3/4 or 75% and RaisedButton by 1/4 or 25%
by this concept i created new Row and putted in it
TextField its flex is equal to top one .
Container its flex is equal to Raisedbutton's flex .
and the edited code is :
`
Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
flex: 3,
child: TextField(),
),
Expanded(
flex: 1,
child: RaisedButton(
child: Icon(Icons.search),
onPressed: () {},
),
),
],
// ),
),
Row(
children: <Widget>[
Expanded(
flex: 3,
child: TextField(
enabled: false,
),
),
Expanded(
child: Container(),
flex: 1,
)
],
)
],
))
`

How to align DropdownButton next to a TextField in Flutter?

I would like to vertically align a DropdownButton right next to a TextField.
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
DropdownButton<String>(
...
),
Flexible(
child: TextField(
...
),
),
],
)
The current behavior is:
As you can see, the bottom lines aren't aligned. I guess that's happening due to a differences in height. What would be a good practice to fix that? (I'm guessing not using a fixed height)
My final goal is something like this:
Where both lines and the text of DropdownButton and TextField are vertically aligned.
Hope this helps but I got it working! Key prop that did it for me was setting contentPadding for widgets in row to 0.0
Row(
children: <Widget>[
Flexible(
flex: 2,
child: TextFormField(
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
decoration: InputDecoration(
labelText: 'Width',
contentPadding: EdgeInsets.all(0.0),
),
onChanged: (String newValue) {
_stashItem.width = "$newValue $_widthUnit";
},
)),
Flexible(
flex: 1,
child: DropdownButtonFormField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(0.0)
),
value: _widthUnit,
items: ['cm', 'm', 'in', 'ft', 'yd']
.map((String unit) =>
DropdownMenuItem<String>(
value: unit, child: Text(unit)))
.toList(),
onChanged: (value) => setState(() {
_widthUnit = value;
})),
)
],
),
A bit late, but I had the same issue albeit with a slightly different layout:
I used TextFormField rather than TextField.
I used DropdownButtonFormField rather than DropDownButton.
Both fields were wrapped in Flexible widgets within the Row, with mainAxisSize set to MainAxisSize.min.
My text field was laid out to the left of the dropdown.
That being said, setting crossAxisAlignment to CrossAxisAlignment.end worked for me.
Try this:
Row(
mainAxisSize: MainAxisSize.min, // see 3
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible( // see 3
child: DropdownButtonFormField<String>( // see 2
...
),
),
Flexible(
child: TextFormField( // see 1
...
),
),
],
)
I am not sure whether this solution helps you or not, but I think its better than using row.
TextField(
decoration: InputDecoration(
prefix: DropdownButton(underline: Container(), ...)
),
)
Try this:
Row(
Row(mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end
children: <Widget>[
Expanded(
flex: 1
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton<String>(
...
))),
Expanded(
flex: 6
child: TextField(
...
),
),
],
)
Try this:
Container(
decoration: BoxDecoration(
border: Border(
//TODO: Customize the underline here
bottom: BorderSide(
color: Colors.white70,
width: 0.5,
),
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
DropdownButton<String>(
onChanged: (c) {},
underline: Container(),
items: [
DropdownMenuItem<String>(
child: Text('Email'),
)
],
),
Flexible(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
),
),
),
],
),
),
I ended up editing the padding of the TextField's content, and used CrossAxisAlignment.center instead of CrossAxisAlignment.start:
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
DropdownButton<String>(
...
),
Flexible(
child: TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(6.0),
),
),
),
],
)
Result:
(You see space between them due to a SizedBox added)
You can simply decrease contentPadding in InputDecoration of DropdownButtonFormField