Flutter - min spacing between Row/Column items - flutter

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

Related

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.

Flutter: how to center a child, but set a limit on how big it can grow on one side of the margin

I have a home/login screen which is made up of a column that fills the entire screen like so:
Column(
children: <Widget>[
Expanded(
child: Container(
child: Logo(),
),
),
showThis ? This() : That(),
],
),
The second child of the column is dynamic and can have different heights, and this screen will have inputs so the keyboard will also affect the height.
I want to center Logo() vertically within the container when it's small (e.g. when keyboard is active), but limit how much the 'top margin' is able to grow, so that when the keyboard is hidden and This()/That() is small enough, Logo() will be in a static position on the screen, say 150 from the top (no longer centred vertically).
One method I have tried was using 2 empty Expanded() above and below Logo() and wrapping the top part in a ConstraintedBox(), but I am not able to get it to behave correctly.
Have you tried with Center() and also if you wanna in a specific position use Stack, for example
Stack(
children: <Widget>[
showThis(),
Positioned(top: 150, child: Logo())
],
)
This is what ended up working for me:
Column(
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
// constrain top spacing with a max height
Flexible(child: Container(height: 160)),
_logo(),
Spacer(),
],
),
),
_bottomWidget(),
],
),

Flutter: How to add a column widget inside a bottom navigation bar

I've tried the following and got the out, but the body went blank.
Is there any way to add a coloumn or a listview inside a bottom navigation bar
Column(
mainAxisAlignment:MainAxisAlignment.end,
children: <Widget>[
Row(
children: <Widget>[
Expanded(
//button1
),
Expanded(
//button2
),
Expanded(
//button3)
),
Row(
children: <Widget>[
Expanded(
//button4
),
Expanded(
//button5)
],
)
],
),
Apart from the issue posed by Expanded widget (as pointed out in the answer by alexandreohara),
Column's mainAxisSize attribute is set to MainAxisSize.max by default. That means the column will try to occupy all the space available (the entire screen height).
Setting Column's mainAxisSize to MainAxisSize.min will wrap the Column widget to occupy the least possible space(vertically) and not span the entire screen.
Following is the way it can be done:
Column(
mainAxisSize: MainAxisSize.min,
children: [...]
);
There's no problem using a Column in a BottomNavigationBar. I think that your problem is wrapping everything in Expanded. It doesn't know the width of the widgets inside, and because of that, it will return blank.
Try to remove those Expanded widgets and try this:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween
children: [FlatButton(...), FlatButton(...)],
)

Text inside nested Row is not wrapping unless enclosing column is wrapped in Flexible widget

The text inside my Text widget is not wrapping, even when wrapped in a Flexible widget. I found a workaround but it involves wrapping a Column widget inside a Flexible widget which I am not sure is best practice.
I have seen many similar answers online, but none for my exact problem. It is relevant that my text widget in question is nested inside the following hierachy Row -> Column -> Row
A rough idea of how this layout should look:
Here is the original code. When run the text overflows the screen rather than wrapping.
Row(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("top column"),
Row(
children: [
Text("left row"),
Text(
"this is the text that needs to wrap, this is the text that needs to wrap",
),
],
),
],
crossAxisAlignment: CrossAxisAlignment.start,
),
Text("right side"),
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
);
Here is code that solves my problem, but it involves wrapping both the Text widget AND the outer Column widget in a Flexible widget:
Row(
children: [
Flexible( // added Flexible widget, but doesn't seem correct.
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("top column"),
Row(
children: [
Text("left row"),
Flexible( // added Flexible widget
child: Text(
"this is the text that needs to wrap, this is the text that needs to wrap",
),
)
],
),
],
crossAxisAlignment: CrossAxisAlignment.start,
),
),
Text("right side"),
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
);
Is there a better way to achieve this wrapping or is enclosing the Column in a Flexible widget a satisfactory approach?
Your approach is right, here's why :
You managed to the problem of the inner Row long text by wrap it into a Flexible,to prevent an overflow in the horizontal axis.This works perfectly if this is your whole tree,but this isn't the case.
Up on your widget tree there is no horizontal constraint limiting the width of children.Column wraps in the vertical axis, so the children of the upper-most Row one with fixed width (Text("right side")) and the other is unbounded one (Column).
When you wrapped the Column with Flexible, it made children bounded horizontally. Another approach would be to use a Container, but it is not the best one as it needs you to give the width before build.

What would be a good way for a widget to take 1/3 of the screen?

I am trying to make a widget take up 1/3 the screen regardless of the phone orientation. How do I accomplish this?
I got what I wanted by using a Column and wrapping the contents in Flexible and changing the flex to get the child to take up 1/3 the screen:
new Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Flexible(flex: 2, child: new SizedBox()),
new Flexible(flex: 1, child: createTextBox())
]
);
There's a few widgets that might help: AspectRatio, Column/Expanded, and CustomSingleChildLayout in particular. It's hard to give a good answer without knowing exactly what you want to do though.
You should try using Expanded widgets as the children of your row, like so:
new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
new Expanded(
child: yourFirstContentWidget,
),
new Expanded(
child: yourNextContentWidget,
),
new Expanded(
child: yourLastContentWidget,
)
]
)
The Expanded widgets will each try to fill as much space of the row as possible. Since there are three of them, they will have to share the space and you'll end up with each taking up 1/3 of the row.