How to add a ListView to a Column in Flutter?
FlutterListviewDartFlutter LayoutFlutter WidgetFlutter Problem Overview
I'm trying to construct a simple login page for my Flutter app. I've successfully built the TextFields and log in/Sign in buttons. I want to add a horizontal ListView. When I run the code my elements disappear, if I do it without the ListView, it's fine again. How can I do this correctly?
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("Login / Signup"),
),
body: new Container(
child: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new TextField(
decoration: new InputDecoration(
hintText: "E M A I L A D D R E S S"
),
),
new Padding(padding: new EdgeInsets.all(15.00)),
new TextField(obscureText: true,
decoration: new InputDecoration(
hintText: "P A S S W O R D"
),
),
new Padding(padding: new EdgeInsets.all(15.00)),
new TextField(decoration: new InputDecoration(
hintText: "U S E R N A M E"
),),
new RaisedButton(onPressed: null,
child: new Text("SIGNUP"),),
new Padding(padding: new EdgeInsets.all(15.00)),
new RaisedButton(onPressed: null,
child: new Text("LOGIN"),),
new Padding(padding: new EdgeInsets.all(15.00)),
new ListView(scrollDirection: Axis.horizontal,
children: <Widget>[
new RaisedButton(onPressed: null,
child: new Text("Facebook"),),
new Padding(padding: new EdgeInsets.all(5.00)),
new RaisedButton(onPressed: null,
child: new Text("Google"),)
],)
],
),
),
margin: new EdgeInsets.all(15.00),
),
),
);
Flutter Solutions
Solution 1 - Flutter
I've got this problem too. My solution is use Expanded
widget to expand remain space.
Column(
children: <Widget>[
Expanded(
child: horizontalList,
)
],
);
Solution 2 - Flutter
Reason for error:
Column
expands to the maximum size in main axis direction (vertical axis), and so does the ListView
.
Solutions:
So, you need to constrain the height of the ListView
. There are many ways of doing it, you can choose that best suits your need.
-
If you want to allow
ListView
to take up all remaining space insideColumn
, useExpanded
.Column( children: <Widget>[ Expanded( // <-- Use Expanded child: ListView(...), ) ], )
-
If you want to limit your
ListView
to a certainheight
, useSizedBox
.Column( children: <Widget>[ SizedBox( height: 200, // Constrain height. child: ListView(...), ) ], )
-
If your
ListView
is small, you may tryshrinkWrap
property on it.Column( children: <Widget>[ ListView( shrinkWrap: true, // Set this ) ], )
-
If you want to make
ListView
to as small as it can be, useFlexible
withListView.shrinkWrap
:Column( children: <Widget>[ Flexible( // <-- Use Flexible child: ListView( shrinkWrap: true, // and set this ), ) ], )
Solution 3 - Flutter
You can check console output. It prints error:
> The following assertion was thrown during performResize(): The horizontal viewport was given unbounded height. Viewports expand in the cross axis to fill their container and constrain their children to match their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of vertical space in which to expand.
You need to add a height constraint to your horizontal list. E.g. wrap in Container with height:
Container(
height: 44.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
RaisedButton(
onPressed: null,
child: Text("Facebook"),
),
Padding(padding: EdgeInsets.all(5.00)),
RaisedButton(
onPressed: null,
child: Text("Google"),
)
],
),
)
Solution 4 - Flutter
Expanded Widget increases its size as much as it can with the space available Since ListView essentially has an infinite height it will cause an error.
Column(
children: <Widget>[
Flexible(
child: ListView(...),
)
],
)
Here we should use the Flexible
widget as it will only take the space it required as Expanded take full screen even if there are not enough widgets to render on full screen.
Solution 5 - Flutter
I have SingleChildScrollView
as a parent, and one Column
Widget and then List View Widget as last child.
Adding these properties in List View Worked for me.
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.vertical,
Solution 6 - Flutter
As have been mentioned by others above,Wrap listview with Expanded is the solution.
But when you deal with nested Columns you will also need to limit your ListView to a certain height (faced this problem a lot).
If anyone have another solution please, mention in comment or add answer.
Example
SingleChildScrollView(
child: Column(
children: <Widget>[
Image(image: ),//<< any widgets added
SizedBox(),
Column(
children: <Widget>[
Text('header'), //<< any widgets added
Expanded(child:
ListView.builder(
//here your code
scrollDirection: Axis.horizontal,
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
return Container();
}
)
),
Divider(),//<< any widgets added
],
),
],
),
);
Solution 7 - Flutter
Here is a very simple method. There are a different ways to do it, like you can get it by Expanded
, Sizedbox
or Container
and it should be used according to needs.
-
Use
Expanded
: A widget that expands a child of aRow
,Column
, orFlex
so that the child fills the available space.Expanded( child: ListView(scrollDirection: Axis.horizontal, children: <Widget>[ OutlineButton(onPressed: null, child: Text("Facebook")), Padding(padding: EdgeInsets.all(5.00)), OutlineButton(onPressed: null, child: Text("Google")), Padding(padding: EdgeInsets.all(5.00)), OutlineButton(onPressed: null, child: Text("Twitter")) ]), ),
Using an Expanded
widget makes a child of a Row
, Column
, or Flex
expand to fill the available space along the main axis (e.g., horizontally for a Row or vertically for a Column).
-
Use
SizedBox
: A box with a specified size.SizedBox( height: 100, child: ListView(scrollDirection: Axis.horizontal, children: <Widget>[ OutlineButton( color: Colors.white, onPressed: null, child: Text("Amazon") ), Padding(padding: EdgeInsets.all(5.00)), OutlineButton(onPressed: null, child: Text("Instagram")), Padding(padding: EdgeInsets.all(5.00)), OutlineButton(onPressed: null, child: Text("SoundCloud")) ]), ),
If given a child, this widget forces its child to have a specific width and/or height (assuming values are permitted by this widget's parent).
-
Use
Container
: A convenience widget that combines common painting, positioning, and sizing widgets.Container( height: 80.0, child: ListView(scrollDirection: Axis.horizontal, children: <Widget>[ OutlineButton(onPressed: null, child: Text("Shopify")), Padding(padding: EdgeInsets.all(5.00)), OutlineButton(onPressed: null, child: Text("Yahoo")), Padding(padding: EdgeInsets.all(5.00)), OutlineButton(onPressed: null, child: Text("LinkedIn")) ]), ),
The output to all three would be something like this
Solution 8 - Flutter
Actually, when you read docs the ListView should be inside Expanded Widget so it can work.
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Align(
child: PayableWidget(),
),
Expanded(
child: _myListView(context),
)
],
));
}
Solution 9 - Flutter
You can use Flex
and Flexible
widgets. for example:
Flex(
direction: Axis.vertical,
children: <Widget>[
... other widgets ...
Flexible(
flex: 1,
child: ListView.builder(
itemCount: ...,
itemBuilder: (context, index) {
...
},
),
),
],
);
Solution 10 - Flutter
Column(
children: <Widget>[
Text('Leading text widget'),
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: <Widget>[
ListTile(
leading: Icon(Icons.map),
title: Text('Map'),
),
ListTile(
leading: Icon(Icons.photo_album),
title: Text('Album'),
),
ListTile(
leading: Icon(Icons.phone),
title: Text('Phone'),
),
],
),
Text('More widget'),
],
);
just use
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
properties in listView
Solution 11 - Flutter
Wrap your Listview with Expanded Widget
Solution 12 - Flutter
[Solution Preview] - [List Items are scrollable but heading is fixed]
I have very small & straight forward answer, see putting listview inside column will force column to expand infinitely, which is basically an error thing.
Now if you put physics: NeverScrollableScrollPhysics(),
like others suggested, in listview then whats the point of having listview if you disable scrolling inside it..
There is an easy fix, frankly I landed on this by hit and trial. Let me give you small explanation after code.
Column(
children: [
Text(
"All Bookings",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: Colors.brown[700]),
),
Expanded(
child: Container(
margin: EdgeInsets.only(top: 24),
child: ListView.builder(
itemCount: 30,
itemBuilder: (BuildContext context, int index) => ListTile(
title: Text("List Item ${index + 1}"),
),
),
),
),
],
)
I had requirement to have title inside Column as first element & then put a Listview so that user can have scrolling list. This is a generic kind of requirement. You can put this in Bottom Sheet or Modal too.
Code Explanation:
- I kept first child as heading inside Column ok (which i donot want to scroll away, i want it to be fixed)
- I have Expanded child inside column, which is like acquire all the "remaining space" in column.
- Inside that I kept container (Just to put some space between title & list view with margin) this is optional, you can remove container and it will still work.
- Now the Listview is well constrained and it won't try to stretch infinitely in column. As Expanded widget already constrained it.
Please correct me if I am wrong anywhere or if this code doesn't work (it works as of now without errors :)
Solution 13 - Flutter
You need to do 2 things:
- wrap
Column
insideSingleChildScrollView
- add
shrinkWrap: true
andphysics: NeverScrollableScrollPhysics()
inListView
Why it works:
As I uderstand, NeverScrollableScrollPhysics
disable scrolling of ListView
.
So, scroll works with SingleChildScrollView
.
If I am wrong, comment bellow.
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Filter'),
ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: rides.length,
itemBuilder: (BuildContext context, int index) {
# return some widget
}
),
Solution 14 - Flutter
In my case, I was using
- singleChildScrollView
- Column
- Container
- FutureBuilder - Listview
and I wanted to scroll last scroll view with the whole column for this add
physics: NeverScrollableScrollPhysics(),
this line in your listview.
Solution 15 - Flutter
Try using Slivers:
Container(
child: CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate(
[
HeaderWidget("Header 1"),
HeaderWidget("Header 2"),
HeaderWidget("Header 3"),
HeaderWidget("Header 4"),
],
),
),
SliverList(
delegate: SliverChildListDelegate(
[
BodyWidget(Colors.blue),
BodyWidget(Colors.red),
BodyWidget(Colors.green),
BodyWidget(Colors.orange),
BodyWidget(Colors.blue),
BodyWidget(Colors.red),
],
),
),
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
delegate: SliverChildListDelegate(
[
BodyWidget(Colors.blue),
BodyWidget(Colors.green),
BodyWidget(Colors.yellow),
BodyWidget(Colors.orange),
BodyWidget(Colors.blue),
BodyWidget(Colors.red),
],
),
),
],
),
),
)
Solution 16 - Flutter
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("Login / Signup"),
),
body: new Container(
child: new Center(
child: ListView(
//mainAxisAlignment: MainAxisAlignment.center,
scrollDirection: Axis.vertical,
children: <Widget>[
new TextField(
decoration: new InputDecoration(
hintText: "E M A I L A D D R E S S"
),
),
new Padding(padding: new EdgeInsets.all(15.00)),
new TextField(obscureText: true,
decoration: new InputDecoration(
hintText: "P A S S W O R D"
),
),
new Padding(padding: new EdgeInsets.all(15.00)),
new TextField(decoration: new InputDecoration(
hintText: "U S E R N A M E"
),),
new RaisedButton(onPressed: null,
child: new Text("SIGNUP"),),
new Padding(padding: new EdgeInsets.all(15.00)),
new RaisedButton(onPressed: null,
child: new Text("LOGIN"),),
new Padding(padding: new EdgeInsets.all(15.00)),
new ListView(scrollDirection: Axis.horizontal,
children: <Widget>[
new RaisedButton(onPressed: null,
child: new Text("Facebook"),),
new Padding(padding: new EdgeInsets.all(5.00)),
new RaisedButton(onPressed: null,
child: new Text("Google"),)
],)
],
),
),
margin: new EdgeInsets.all(15.00),
),
),
);
Solution 17 - Flutter
Also, you can try use CustomScrollView
CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
final OrderModel order = _orders[index];
return Container(
margin: const EdgeInsets.symmetric(
vertical: 8,
),
child: _buildOrderCard(order, size, context),
);
},
childCount: _orders.length,
),
),
SliverToBoxAdapter(
child: _buildPreloader(context),
),
],
);
Tip: _buildPreloader
return CircularProgressIndicator
or Text
In my case i want to show under ListView some widgets. Use Column
does't work me, because widgets around ListView inside Column showing always "up" on the screen, like "position absolute"
Sorry for my bad english