Flutter row overflfow with list - flutter

I have a list I'm mapping:
List<Widget> names = post.names
.map(
(c) => new Padding(
padding: EdgeInsets.all(8),
child: new Text('' + c['name']),
),
)
.toList();
And displaying:
new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: names,
),
However, the row overflows to right if it has too many items in it. I tried to wrap it to Expanded / Flexible widgets, but that causes error about the parent widget not having height.
If I try to use:
crossAxisAlignment: CrossAxisAlignment.stretch,
I get:
BoxConstraints forces an infinite height.
I also tried to use Expanded inside the Row, however that is not possible as I'm creating the children from the list and that causes error.
How to achieve a name list which also expands vertically based to amount of items?

You need to use Wrap instead of Row like this.
Wrap(
children: names,
//...
),

If you want the widgets to be scrollable horizontally, use a list view and set the axis to horizontal.
But if you want the widgets to wrap, then you need to build a grid instead of a row.
Check out this post: Flutter - Layout a Grid

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

Wrap Scaffold in Row

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: [],
),
),
],
),
)

Separate and show priority items on top of a ListView? (Pinned Item functionality)

How to add the 'pinned item' functionality, similar to Google Keep, on a ListView?
I tried doing 2 list view, and putting the pinned one on top of a Column. But the problem is they scrolled separately, and if I wrapped the column in a Singlechildscrollview, it just gives error.
Am I on the right track of doing it or there is a way by just using a single list view?
Implement if you want:
add an extra field to your object: bool pinned -> then you sort the list to make sure the pinned items are on top of the list
put a GestureDetector around the item and use the onTap to set the pinned value -> pinned = !pinned
Or try this package I just found:
https://pub.dev/packages/pinnable_listview
I think I got the Singlechildscrollview worked the way I want it to. I just have to set the ListView shrinkWrap: true, and physics: NeverScrollableScrollPhysics(). I'm not sure if this is a good idea tho, since most people say that shrinkWrap is quite a heavy operation to use.
SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Pinned'),
PinnedListItemHere(), //ListView of Pinned Items
Divider(
height: 25.0,
thickness: 2.0,
),
Text('Others'),
UnpinnedListItemHere(), //ListView of Unpinned Items
],
),
),

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.

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")
])