Wrap Scaffold in Row - flutter

I want to built a split screen for larger devices. One half should be as small as possible but as large as needed and the other half should occupy the rest of the screen.
I figured I'd use a Row containing two Scaffolds (one wrapped in a Expanded widget) like so:
Row(children: [
Scaffold(appBar: MyAppBar1(), body: Container()),
Expanded(child: Scaffold(appBar: MyAppBar2(), body: Container())),
])
However, I get the following error message when wrapping a Scaffold inside a Row:
RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
I know that I could just wrap the Scaffold inside a SizedBox with a fixed width, but I want the Scaffold to automatically take the right size.

Scaffold itself doesn't have a width constraint, so it will try to occupy as much space as possible (if I'm remembering correctly), and Row on its part won't try to constrain it, hence the error.
You have two options:
wrap the Scaffold in another Expanded, then use the flex argument on both the Expanded to give them size relative to each other (i.e., if one has flex: 1 and the other flex: 2, the second one will have twice the size of the first)
wrap the Scaffold in a ConstrainedBox and set the constraints yourself, which I guess in this case would be the maxWidth set on the smaller side
As others pointed out, anyway, if you don't really need another Scaffold, you can simply use two Column and get a similar result.

You do not need to use two Scaffolds. Use two columns inside one Column in Scaffold. Wrap the second Column with Expanded. This way your first part will take as much space as needed and the second part will take the remaining space.
home: Scaffold(
body: Column(
children: [
Column(
children: [],
),
Expanded(
child: Column(
children: [],
),
),
],
),
)

Related

How to prevent failedAssertion: size.isFinite in Flutter

I had a very basic Flutter layout which looked something like this:
Column
widget1
expanded
widget2
This worked great. Widgets 1 and 2 were rendered and my main "expanded" widget was taking the rest of the screen, great!
Next I wanted to add two buttons on each side of my expanded widget. So I tried this:
Column
widget1
Row
button1
expanded
button2
widget2
Now Flutter throws a layout error: failedAssertion: size.isFinite
Reading about it online, people are saying you cannot put an Expanded inside a Row or a Column because they use infinite main axis length, so if the child is also infinite this causes problems. However, I already had Expanded inside a Column and that worked fine! Why is putting it inside a Row problematic?
One SO suggestion was to put mainAxisSize: MainAxisSize.min in the Row, but that does not help.
Some of the other suggestions were to put the widget inside a Container with fixed sizes. This does resolve the error, but now the widget goes off screen. And this sort of defies the whole purpose of Flutter responsive UI. Why would anyone want to create a fixed sized object on a platform where screen sizes vary widely?
What am I doing wrong here? Seems I am misunderstanding something fundamental here...
it works fine and doesn't through any error
Column(
children:[
Container(
height:50,
width:50,
color:Colors.red),
Row(
children:[
Container(
height:50,
width:50,
color:Colors.red),
Expanded(
child:Text('hgdhj hdgakhjgck dgfkejg')
),
Container(
height:50,
width:50,
color:Colors.red),
]),
Container(
height:50,
width:50,
color:Colors.red),
])

Why does ListView ignore constraints

Why does a ListView completely ignore imposed constraints?
#override
Widget build(BuildContext context) {
return Padding(
child: Container(
constraints: BoxConstraints(maxWidth: 500),
child: ListView(
children: buildList(data),
),
),
);
}
The displayed ListView does not seem to be bothered at all with the maxWidth:500 of the parent container (same if replaced with a ConstrainedBox) and all elements (which are Rows) go full screen width.
Why?
The solution is to work with width of children instead, but still I'd much rather constrain the entire listView, and also if there's a constraint, shouldn't everything inside be forced not to exceed it?
EDIT: After hours of trying various things it finally works. Turns out the list view needed to a child of a Center, otherwise it would not pay any attention to SizedBoxes, ConstrainedBoxes, Containers etc. you'd put on it or its children and stretch full screen no matter what.
What are the parent widgets of the Padding(child: Container(... list view ))? I mean are you sure that a parent is not imposing its constraints on its children? Try do replace your ListView with Container(color: Colors.red, height: 100) and see if it respects the constraints. If it does not, there probably is a parent widget with infinite width constraint or something like that!
A solution can be wrap your Container with an UnconstrainedBox but I would recommend first checking my first point :D

How to Keep the elements on ends in Row() widget in flutter?

I am using below Row widget in flutter , which is nested in a Column widget and on screen it appears shared in the screenshot
I want to the Row elements to appear at extreme ends with some padding. How can I do that?
Row(
children: [
SizedBox(width:20,),
Text("Mark ALL READ"),
SizedBox(width:200,),
Text("Clear All"),
],
),
Setting the mainAxisAlignment property of the row to MainAxisAlignment.spaceAround should place the elements on both ends of the row.
To add some padding you should be able to just place the whole Row() widget into a Padding() widget.

"RenderStack object was given an infinite size during layout" when using Positioned inside a Stack

I'm creating a widget that presents a Stack inside a Container. Inside the Stack there is a dynamic Column inside a Positioned widget, which sticks the Column to the Bottom.
I am trying to wrap the Stack in a SingleChildScrollView, that if the dynamic Column will have lots of children it will be able to scroll.
But after I add the scroll view I get this error message:
RenderStack object was given an infinite size during layout.
A scrollView doesn't have height, it will use infinite height for it's children. So the stack should be wrapped in a sizedBox widh a known height in case that you want that. If you want the stack to fill the screen then remove the singleChildScrollview completely. And if you want the stack to be scrollable from the inside. Just add SingleChildScrollView inside the stack
return Scaffold(
body: Container(
color: Colors.blue[100],
child: Stack(
children: [
Positioned.fill(child: SingleChildScrollView(child: MyColumn()))
],
),
),
);
EDIT 1:
Ok the problem is the layout itself. Since you only use the stack to position the image. And you know the widht and height of the image, and the background shape fills all the items. We could
Isolate the stack only to the image, and use padding and some calculation to have the layout build in a similar way.
Then render everything else inside a normal column
My implementation https://dartpad.dev/230b14d8f0b22b45929a75c208786257
From the RenderStack documentation:
First, the non-positioned children (those with null values for top, right, bottom, and left) are laid out and initially placed in the upper-left corner of the stack. The stack is then sized to enclose all of the non-positioned children. If there are no non-positioned children, the stack becomes as large as possible.
Since all of your Stack's children are positioned, Stack will match the maximum size constraint passed down by the SingleChildScrollView. This size has infinite height, so the Stack is forced to have infinite height as well.
To fix this, you will need to find another way to accomplish what you want. One option that comes to mind involves a ConstrainedBox providing a minimum height (obtained from a LayoutBuilder), a non-positioned Column, and a bottomCenter alignment on the Stack itself. This is similar to the first code sample in the SingleChildScrollView documentation:
LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
// This ensures that the Stack fills the entire viewport,
// even if the Column is small.
constraints: BoxConstraints(
minHeight: constraints.maxHeight,
),
child: Stack(
// Place the only non-positioned child (the column) at the bottom
alignment: Alignment.bottomCenter,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [ /* ... */ ]
)
]
)
)
);
}
)

ListTile with wrap_content width

Now when I add a ListTile inside a view (no matter its Column,ListView,...) It gets whole width, I want it to be kinda wrap_content as we have in android.
I know this is an old post but here is a solution I found for future reference:
You can use the IntrinsicWidth widget to stop the ListTile from expanding.
Container(
child: IntrinsicWidth(
child: Column(
children: [
ListTile(title: Text("Hello")),
ListTile(title: Text("There")),
],
)
)
)
As far as I can tell this is not how you are supposed to use ListTile. In the docs it even says:
ListTile requires fixed width constraints
Also, regarding IntrinsicWidth the docs say:
This class is useful, for example, when unlimited width is available and you would like a child that would otherwise attempt to expand infinitely to instead size itself to a more reasonable width. [...] This class is relatively expensive, because it adds a speculative layout pass before the final layout phase. Avoid using it where possible.
may be like this
Row(
children: <Widget>[
ListTile(),
Text("hell")
])