408

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

20 Answers 20

588

I've got this problem too. My solution is use Expanded widget to expand remain space.

Column(
  children: <Widget>[
    Expanded(
      child: horizontalList,
    )
  ],
);
5
  • 5
    This is a great solution because it allows for variable sized heights/widths of the ListView, like when you want it to just take up the remaining space. It allows you to account for varying screen sizes when it's too difficult to know the exact height/width. Jul 26, 2019 at 12:26
  • 5
    This should be the accepted answer. This solution allows the ListView to take the rest of the screen without having to deal with media query. Jul 31, 2019 at 2:46
  • 1
    I'm too new to Flutter to know why this works, but I'm glad it does. Thank you. Flutter's error messages weren't very helpful to explain the root cause of this problem for a non-expert.
    – devdanke
    Jun 21, 2020 at 17:27
  • 1
    simple and what i was looking for .! Would there be any hit on performance and rendering though ?
    – mykey
    Feb 12, 2021 at 2:47
  • 1
    Can someone explain what causes this problem and why Expanded fixes it? Oct 12, 2021 at 19:40
401

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.


  1. If you want to allow ListView to take up all remaining space inside Column, use Expanded.

    Column(
      children: <Widget>[
        Expanded( //        <-- Use Expanded 
          child: ListView(...),
        )
      ],
    )
    

  1. If you want to limit your ListView to a certain height, use SizedBox.

    Column(
      children: <Widget>[
        SizedBox(
          height: 200, // Constrain height.
          child: ListView(...),
        )
      ],
    )
    

  1. If your ListView is small, you may try shrinkWrap property on it.

    Column(
      children: <Widget>[
        ListView(
          shrinkWrap: true, // Set this
        )
      ],
    )
    

  1. If you want to make ListView to as small as it can be, use Flexible with ListView.shrinkWrap:

    Column(
      children: <Widget>[
        Flexible( //        <-- Use Flexible 
          child: ListView(
            shrinkWrap: true, // and set this
          ),
        )
      ],
    )
    
2
  • 4
    your 3rd point is something I highly recommend all beginners to take note of! Dec 22, 2021 at 8:52
  • Remember that the listview also can expand with Width, so if your SizedBox isn't working include the Width limit. Jun 30, 2022 at 9:16
155

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 SizedBox with height:

SizedBox(
  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"),
      )
    ],
  ),
)
2
  • 12
    the next two answers give another two solutions and explain what's happening.
    – pashute
    Oct 2, 2019 at 11:28
  • 2
    Have any suggest to use dynamic height instead of fix the height of listview?
    – Sinh Phan
    Apr 17, 2021 at 3:25
48

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.

0
45

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,
2
  • 1
    scrollDirection: Axis.vertical is the default, so that's not part of the solution. Also, this disables scrolling on the list.
    – Loolooii
    May 30, 2021 at 17:19
  • That has to be an accepted answer! Problem with Expanded and Flexible is flex, which takes up all the space which you planned for a different flexible widget. shrinkWrap solves that while physics disables overflow scrolling effect.
    – Krin-San
    Nov 16, 2021 at 23:14
14

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

     ],
   ), 
  );
3
  • 2
    in nested columns don't use expanded just use shrikWrap: true, physics: NeverScrolPhysics() properties in listView Aug 5, 2020 at 23:22
  • Wrapping the overflowing Column Widget(Check the error message in your terminal you should see the file and line causing the error) with a SingleChildScrollView widget worked for me.
    – F KIng
    Nov 19, 2020 at 15:17
  • Thanks for reply, Now You could use shrink , sizedbx or flexiable with fit as mention by @CopsOnRoad aboce
    – UN..D
    Apr 2, 2022 at 9:37
11

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

}

9

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) {
            ...
        },
        ),
    ),
],

);

1
  • 1
    why Flex? can you explain? I think the OP is asking how toadd ListView in a Column specifically.
    – Gel
    Dec 3, 2020 at 16:59
8

Wrap your Listview with Expanded Widget

2
  • 1
    Could you elaborate more on why wrapping the ListView with Expanded solves this?
    – croxx5f
    Dec 22, 2021 at 15:17
  • 1
    This is covered with a lot more detail by several other answers. Please review existing answers before submitting a new one. If you found previous answers useful, upvote them as a way of validating their approach. Please don't repeat answers, unless you have significantly more detail to add. Dec 23, 2021 at 0:33
7

You need to do 2 things:

  • wrap Column inside SingleChildScrollView
  • add shrinkWrap: true and physics: NeverScrollableScrollPhysics() in ListView

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

1
  • 1
    Clear example and it works perfect.
    – cwhisperer
    Mar 2, 2023 at 13:59
7

[Solution Preview] - [List Items are scrollable but heading is fixed]

enter image description here

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:

  1. I kept first child as heading inside Column ok (which i donot want to scroll away, i want it to be fixed)
  2. I have Expanded child inside column, which is like acquire all the "remaining space" in column.
  3. 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.
  4. 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 :)

6
  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

3
  • 1
    Mind explaining your answer a bit? Oct 20, 2020 at 17:06
  • 1
    the question is how to add listview in a column I think this solved it for me. Wonder why this is not voted up.. Maybe im missing something from that popular answer up there?
    – Gel
    Dec 3, 2020 at 16:56
  • I need to wrap Column as child of SingleChildScrollView
    – mahfuz
    Mar 13, 2021 at 15:20
4

You can wrap your list Flexible I hope this help you!

 Flexible(
      child: ListView(
          shrinkWrap: true,
          primary: true,
          scrollDirection: Axis.horizontal,
          children: <Widget> [
            Wrap(
              spacing: 12,
              runSpacing: 12,
              children: List<Widget>.generate(5, (index) {
                return MyChip(
                  onChange: (p0) {},
                );
              }),
            )
          ]),
      )
1
  • immediate resolution, thanks Jun 8, 2023 at 10:20
1

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

1

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.

1

Instead, I think you need to use an expanded widget.

Column (
  children: <Widget>[
    new TextField(
    decoration: new InputDecoration(
    labelText: "Search something"
    ),
    Expanded(
      ListView(),
    ),
  ]
)
1

If you have a Nested Column or Have a ListView inside a column and you dont want to scroll your first column items and want to minimize the size of your column and dont wanna use Expanded then my comment is for you.

Example: enter image description here

What you should do is use Flex and Flexible.

Example with Nested column: Use Flex instead of first Column

Flex(
  direction: Axis.vertical,
  mainAxisAlignment: MainAxisAlignment.start,
  mainAxisSize: MainAxisSize.min,
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [

   widgets_that_you_dont_wants_to_scroll(...),
   widgets_that_you_dont_wants_to_scroll(...),

   Flexible(
      child: SingleChildScrollView(
         child: Column(
            children: [
              ... 
             ]
            ),
          ),
        ),
      ]
    ),

Example for ListView in Column: use Flex instead of first column

Flex(
  direction: Axis.vertical,
  mainAxisAlignment: MainAxisAlignment.start,
  mainAxisSize: MainAxisSize.min,
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [

   widgets_that_you_dont_wants_to_scroll(...),
   widgets_that_you_dont_wants_to_scroll(...),

   Flexible(
     child: ListView.builder(
              itemCount: 4,
              shrinkWrap: true, // Must add
              itemBuilder: (context, index) {
                 return ...
              },
           ),
        ),
      ]
    ),
0

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

Don't forget to rebuild/restart the app as the hot reload did not reflect or apply when I added an Expanded around my ListView

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.