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

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.

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),
]),
))
]),
),
);

In flutter, how to position radio buttons side by side but align to the left?

I have two RadioListTiles side by side in a row, but I do not want them to take up the entirety of the row. Currently each take up half the width of the entire row and spaced apart.
I want each radio button to take up less space (or just enough) and be left-aligned, and not be so spaced apart. I have tried wrapping each in Expanded or Flexible.
builder: (FormFieldState<NameLineSelection> formstate) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: RadioListTile<NameLineSelection>(
title: const Text('Single-line'),
value: NameLineSelection.singleLineName,
groupValue: state.nameLineSelection,
onChanged: (NameLineSelection? value) {
_saveForm(fieldValues);
formstate.didChange(value);
BlocProvider.of<VerifyMedicareBloc>(context)
.add(MedicareFormCardNameLineSelectedEvent(
_formValues, value));
},
),
),
Expanded(
child: RadioListTile<NameLineSelection>(
title: const Text('Multi-line'),
value: NameLineSelection.multiLineName,
groupValue: state.nameLineSelection,
onChanged: (NameLineSelection? value) {
_saveForm(fieldValues);
formstate.didChange(value);
BlocProvider.of<VerifyMedicareBloc>(context)
.add(MedicareFormCardNameLineSelectedEvent(
_formValues, value));
},
),
),
],
),
if (formstate.errorText != null ||
formstate.errorText.toString() != 'null')
Text(formstate.errorText.toString(),
style: TextStyle(color: Colors.red)),
],
);
}),
One way would be to wrap the RadioListTile widget with a ConstrainedBox and set a maxWidth like so:
Row(
children: [
Expanded(
child: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 300,
),
child: RadioListTile<NameLineSelection>(
title: const Text('Single-line'),
value: NameLineSelection.singleLineName,
groupValue: state.nameLineSelection,
onChanged: (NameLineSelection? value) {
_saveForm(fieldValues);
formstate.didChange(value);
BlocProvider.of<VerifyMedicareBloc>(context)
.add(MedicareFormCardNameLineSelectedEvent(
_formValues, value));
},
),
),
),
Expanded(
child: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 300,
),
child: RadioListTile<NameLineSelection>(
title: const Text('Multi-line'),
value: NameLineSelection.multiLineName,
groupValue: state.nameLineSelection,
onChanged: (NameLineSelection? value) {
_saveForm(fieldValues);
formstate.didChange(value);
BlocProvider.of<VerifyMedicareBloc>(context)
.add(MedicareFormCardNameLineSelectedEvent(
_formValues, value));
},
),
),
),
],
),

Overflow issue in some iOS and android devices

i have implement radio buttons in one row and tested the ui some devices. In small devices like iphone 5s i got the overflow error.
Widget priority() {
return Column(
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
child: const Text('Priority:'),
),
Row(
children: <Widget>[
radioButton('High', 0),
radioButton('Medium', 1),
radioButton('Low', 2),
],
)
],
);
}
Widget radioButton(String text, int value) {
return Row(
children: <Widget>[
Radio<int>(
activeColor: pinkColor,
value: value,
groupValue: _selected,
onChanged: (int value) {
onChange(value);
}),
Text(text, style: TextStyle(fontSize: 15)),
],
);
}
Hey, Use Expanded Widget To Solve Overflow Issue And For IOS, Android Issue Wrap Whole Widget In SafeArea, Hope This May Help You...
Add SingleChildScrollView it'll work.
Widget priority() {
return Column(
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
child: const Text('Priority:'),
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: <Widget>[
radioButton('High', 0),
radioButton('Medium', 1),
radioButton('Low', 2),
],
))
],
);
}
Widget priority() {
return Column(
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
child: const Text('Priority:'),
),
Wrap(
direction: Axis.horizontal,
children: <Widget>[
radioButton('High', 0),
radioButton('Medium', 1),
radioButton('Low', 2),
],
)
],
);
}
Widget radioButton(String text, int value) {
return Row(
children: <Widget>[
Radio<int>(
activeColor: pinkColor,
value: value,
groupValue: _selected,
onChanged: (int value) {
onChange(value);
}),
Text(text, style: TextStyle(fontSize: 15)),
],
);
}
Replaced Row with Wrap. If Overflow occurs, the overflowing widget will be aligned in the next line. Hope it helps.
Solution Code:
Widget priority() {
return Column(
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
child: const Text('Priority:'),
),
Row(
children: <Widget>[
Expanded(child: radioButton('High', 0),),
Expanded(child: radioButton('Medium', 1),),
Expanded(child: radioButton('Low', 2),),,
],
)
],
);
}
Widget radioButton(String text, int value) {
return Row(
children: <Widget>[
Radio<int>(
activeColor: pinkColor,
value: value,
groupValue: _selected,
onChanged: (int value) {
onChange(value);
}),
Text(text, style: TextStyle(fontSize: 15)),
],
);
}
The reason why you faced it in a some devices and not in the others was that all devices have different screen sizes.
Expanded Widget ensures that it's child widget covers all the available space while it's among other widgets in a List of Widgets ([])
When we use it on multiple widgets then it equally divides the space among each other. You can control the size taken by each widget using the flex property.
If you introduce a non-Expanded widgets between Expanded widgets then the non-Expanded once are first laid out before the Expanded widget(s).
(Atleast that's what mentioned in Flutter's Widget of the Week video. However, I think it has got something more complex to it which we don't need to know.)
Tip: Avoid using functions in these places...Use classes instead.
A beautiful tutorial by the official Flutter Team:
https://flutter.dev/docs/development/ui/interactive

How to position two widget in a same Row?

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,

Is there a way to align a widget to the far right of a row in Flutter?

I have a row in Flutter with two widgets. I'm trying to keep the first widget centered in the middle of the screen and the second widget forced to the far right of the screen.
I've tried using Spacer(). This results in the app returning a blank screen.
I've also tried using Expanded. This sends the second widget off the screen completely.
Trying mainAxisAlignment: MainAxisAlignment.spaceBetween did not seem to have any effect.
#override
Widget build(BuildContext context) {
return new Container(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Container(
child: new GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: Column(
children: <Widget>[
SizedBox(height: 40.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Column(
children: <Widget>[
new Container(
child: Row(
mainAxisAlignment:MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(),
Container(
child: Text(
'Profile',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Lato',
color: Colors.white,
fontSize: 50.0,
fontWeight: FontWeight.w700,
),
),
),
Container(
child: IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
size: 30.0,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OnBoarding()),
);
}),
),
]),
),
),
],
),
],
),
You can use a Row with an Expanded child that contains a Stack. Centre your text with Center and position the icon with Positioned, like so:
[...]
child: Column(
children: <Widget>[
SizedBox(height: 40.0),
Row(
children: <Widget>[
Expanded(
child: Stack(
children: [
Center(
child: Text(...),
),
),
Positioned(
right: 8,
child: IconButton(...),
[...]
Simply just add Spacer() between your main text and the Icon you want to the far right.
For example:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
Text(
'Random test text',
style: TextStyle(color: Colors.white),
),
Spacer(),
IconButton(
icon: Icon(Icons.more_vert_rounded),
color: Colors.white,
onPressed: () {},
),
],
)
I hope this helps you. And I hope the format of the code is readable. Still getting a hang of stackoverflow comments
I did this and worked in my project
child:Row(
**crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,**
children: [
Icon(MaterialCommunityIcons.comment_outline),
Text("0"),
Icon(Icons.favorite_border),
Text("0"),
],
),
I needed align Icons and Text at right in Row widget
Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end
children: [ // put your widget list and be happy ]
)
)
enter image description here
Use a row with this following structure:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(),
Container(
child: Text(
'Profile',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Lato',
color: Colors.white,
fontSize: 50.0,
fontWeight: FontWeight.w700,
),
),
),
Container(
child: IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
size: 30.0,
),
),
),
]
),
what will happen is that the spaceBetween property will divide available space equally between the widgets in the row, so I put an empty Container, and this will force the Text widget to be in the middle of the row and the IconButton in the far end as you desire.
I noticed in your code snippet that you have a Column with a single Row which again contains a single Column , you should eliminate this redundancy to optimize your code and make it easier to debug:
Have you tried setting the mainAxisAlignment of the row to mainAxisAlignment.center?
Imo the easiest way to do this is to create a row with 2 children: The first child is an Expanded Row with all your "main" widgets. The second child is your widget which must be aligned to the end.
Row(
children: [
Expanded(
child: Row(
children: [...mainWidgets...],
),
),
...endWidget...
],
),
Note that Expanded is space-greedy. If you use e.g. MainAxisAlignment.center for your Expanded Row, then your children are drawn across the whole avialable width. If this is not to your liking, Id suggest to wrap the Expanded-Row (not Expanded) inside a Container with "constraints: BoxConstraints(maxWidth: 500)". Obviously Expanded shouldnt be Constrained.
Achieve using Expanded & Align like below inside Row:
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
...some other widgets,
Expanded(
//Expanded will help you to cover remaining space of Row
flex: 1,
child: Align(
//Align with alignment.centerRight property will move the child to righteous inside Expanded
alignment: Alignment.centerRight,
child: const Icon(Icons.arrow_back),
),
),
],
),
Note, the Expanded has to be just inside the Row children: <Widget>[],
othewise suppose you've put the GestureDetector inside Row children: <Widget>[], and inside GestureDetector you have put your Expanded, then it won't
work.
Hope this would help many one.