Flutter SingleChildScrollView with Expanded - flutter

How do you guys solve the following Flutter layout??
I have a screen, where I have to show, as described in the picture: a logo + 3 TextFormFields + 2 buttons + a Container.
Problems:
I need to put all the widgets inside a Column and, the Column inside a SingleChildScrollView so that, when the keyboard pops up, it does not cover the TextFields.
The last widget, the Container, shall take all the remaining screen space on the bottom, but NOT taking more than the screen size. For that, My idea was to use the Expanded widget, so that the Container can expand to the bottom of the screen, but that gives an error:
The following assertion was thrown during performLayout(): RenderFlex children have non-zero flex but incoming height constraints are unbounded.
So I guess my question, in short is, how do I prevent the keyboard to cover the TextFields, while at the same time I force the Container to take all the remaining space on the bottom.
That was my attempt:
SingleChildScrollView(
child: Column(
children: [
Image.asset("assets/images/appLogo.png"),
TextFormField(),
TextFormField(),
TextFormField(),
Row(children: [TextButton(), TextButton()]),
Expanded(child: Container())
],
));

Expanded doesn't know how much size to take. Also the other children don't know their exact size.
Wrap your Image inside a container and give height & width to it. also try wrapping all textfields inside a column or container each.
SingleChildScrollView(
child: Column(
children: [
Container(
width: MediaQuery.of(context).Size.width * 0.4,
height: MediaQuery.of(context).Size.height * 0.2,
child: Image.asset("assets/images/appLogo.png"),
),
Column(
children: [
TextFormField(),
TextFormField(),
TextFormField(),]
)
Row(children: [TextButton(), TextButton()]),
Expanded(child: Container())
],
));
I hope this will work for you.

Related

Flutter: Expanded with respect to parent container

I have a container with screen width*.9. Inside this container, I currently have the following:
SizedBox(
width: MediaQuery.of(context).size.width * .65,
child: Row(
children: [
Expanded(
child: TextSplitter(
wave.message,
context,
Theme.of(context).textTheme.subtitle2!,
)),
],
),
),
I would like to be able to remove the SizedBox wrapping the Row, so that the widget expands into the rest of the space in the parent container. However, currently, removing the sized box leads me to the text disappearing, and throws
RenderFlex children have non-zero flex but incoming width constraints are unbounded.
Extending this sized box leads to overflowing the parent's width, causing an error as well. Any ideas?
Thanks!

Restricting the size of widgets programmatically

I'd like to create the layout shown in the picture below. This shows up fine:
Column( Row, ListView()))
While this renders errors:
Column( Row, Row( ListView(), Column ))
As soon as I replace the inner ListView() with Row( ListView(), Column ), nothing shows up and I get varying error messages, based on various changes I did.
Most often, I see a 'viewport has unlimited horizontal size'.
I guess Listview to be the source of the problem. That said, I'm no aware how to fix it.
Furthermore, I did find various hints on SO, but none fixed the problem.
How do I fix the problem?
Update 1
While the right Column() may be fixed width, the ListView() should take all remaining space of the screen [= availableWidth - WidhtOf(Column())].
put the ListView inside a Container And give it height/width
code
Column(
children: [
Row(
children: [],
),
Row(
children: [
Container(
height: 100,
width: 100,
child: ListView(
children: [
Text(
"1 C/G")
],
)),
Column(
children: [],
)
],
)
],
),
Both Row and Column have a mainAxisSizeparameter where you can set it to MainAxisSize.min so they will take their children's size.
Now, about the ListView, there is a shrinkWrap parameter that makes it so its max size will be its children's size. Another idea might be using a Flexible widget around the ListView, it does almost the same as Expanded, but the difference is: Expanded forces the child to occupy the remaining space, while Flexible allows the children to have any given size smaller than that, and that's because of its fit parameter that by default is FlexFit.loose.

How to make equal width or height constraints between widget in flutter?

In iOS's native AutoLayout constraints, It very easy to make a equal width constraints between ViewA and ViewB . And these two views will get a same width always.
But in flutter ,it seems can't be achived this kindof constraints so easily?
Do I have to make a SizedBox with specific width for both WidgetA and WidgetB explicitly?
You can always put your widgets in a Row(), and wrap every widget in Expanded(). This way they will always have 50% width of the parent Row(). And if you need to constrain the width, just wrap the Row() in a SizedBox().
SizedBox(
width: 500.0,
child: Row(
children: [
Expanded(
child: Container(),
),
Expanded(
child: Container(),
),
],
),
),

ListView in a Row Flutter

What I want to achieve is to have a static Container in the left half and a scroll-able list of items on the right half of the screen:
|----------------------|
| | |
| Container | ListView |
| | |
|----------------------|
It is for a desktop app, so I like this layout. My implementation: (appStatWidgets is a list of containers with text)
Row(
children: [
Container(height: 400, width: 400, color: Colors.green),
Expanded(
child: ListView(
children: appStatWidgets,
),
)
]),
But if i do this, the ListView is invisible and I get:
Vertical viewport was given unbounded height.
But I thought, that
Expanded would fix that.
What works is putting SizedBox instead of Expanded, but that gives me static size and I would like it to be flexible.
Use shrinkwrap: true in your list view parameters, to prevent it from having unbound heights.
And for your Sized box to take half the height for example, use mediaQuery to define the height.
i.e
SizedBox(height: MediaQuery.of(context).size.height * 0.50) This will set it's height to 50% of the screen.
and for ListView(physics, use physics: AlwaysScrollableScrollPhysics().
Row(
children: [
Container(height: 400, width: 400, color: Colors.green),
Expanded(
child:SizedBox(
width:100,
heigth:100,
child:ListView(
children: appStatWidgets,
),
)
)
]),
Like this
For a listview in a row, make sure you set the scroll direction to Axis.horizontal and one more thing make sure you provide your listview a vertical bound, so put it in a container with height only.
Wrap the listview with sized box and provide width and height

Flutter - min spacing between Row/Column items

I try to build layout from picture with no success. How can I do it? (See what I've tried below)
I build Row like this:
final row = Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Item(),
SizedBox(width: _minSpacing),
Item(),
SizedBox(width: _minSpacing),
Item(),
],
);
Works good, but can't downscale content on overflow. So I put this thing inside FittedBox to support downscaling:
final fittedRow = FittedBox(
fit: BoxFit.scaleDown,
child: row,
);
At this point Row stopped to distribute free space between items. It seems FittedBox tries to be as small as possible and don't provide free space for Row. So I also tried to put it inside Container to maybe stretch FittedBox:
Container(
width: double.infinity,
child: fittedRow,
);
But Row still won't spread its children. The best thing I could do, is to set BoxFit.contain - then FittedBox at least start to upscale Row to fill whole screen.
You can use Flexible Widget and assign them flex value.
final row = Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(child: Item(),flex: 1,),
Flexible(child: Item(),flex: 1,),
Flexible(child: Item(),flex: 1,),
],
);
If you wrap your items with Flexible widget and assign them flex value i think you will get you want exactly, it will set up your items automatically depend on phone's screen