Flutter - Listview.builder inside another Listview
Asked Answered
R

8

35

I want my screen to be scrollable so I put everything in a Listview.

Now I want to show another Listview inside to show details of a List. When I try this an error is thrown - " Expanded widgets must be placed inside Flex widgets."

enter image description here

Reims answered 25/11, 2018 at 7:5 Comment(2)
Add shrinkwrap: true in listview.builderRags
Remove the top most container or replace it with columnRags
R
73

Add shrinkWrap: true in listView.builder & Remove the top most Container or replace it with Column.

Rags answered 25/11, 2018 at 15:57 Comment(2)
thank you, this was particularly helpful for placing a listview.builder inside a listView but without the usage of Expanded...Loutitia
note that this will render all of the widgets that inner list contains, meaning it will cause problems with infinite lists or very big onesWarehouseman
M
57

Adding shrinkWrap: true, physics: ScrollPhysics(), inside the listview.builder, in this case the listview.builder need an expanded parent. The physics: ScrollPhysics() will allow it to maintain its state without scrolling back to the first items. Also, you can use physics: NeverScrollableScrollPhysics(), if you don't want the listview.builder to be scrolled by the user.

Malefaction answered 9/4, 2019 at 18:30 Comment(1)
Great! Thanks @CodeMemory, it works perfectly for ListView.builder with dynamics data.Weinberg
P
15

I want my screen to be scrollable so I put everything in a Listview.

I think you should use a CustomScrollView with slivers instead.

If it's the first time your hear about slivers, or if they seem a little bit scary, I suggest you to read this excellent article written by Emily Fortuna.

In your case, I would do something like this:

return CustomScrollView(
  slivers: <Widget>[
    SliverToBoxAdapter(
      // Put here all widgets that are not slivers.
      child: Container(),
    ),
    // Replace your ListView.builder with this:
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return ListTile();
        },
      ),
    ),
  ],
);
Purple answered 25/11, 2018 at 9:23 Comment(0)
F
9

I had this issue when I used two ListViews, one inside another. Nothing has worked for me except this workaround.

In the nested Listview, cover it with a ConstrainedBox and give it some large height. and use 'shrinkWrap: true' both ListViews. Since the shrinkwrap will trim the extra space, that extra height won't be an issue.

Flexible(
  child: ListView(
    children: <Widget>[
      //other Widgets here ...
      ConstrainedBox(
        constraints: BoxConstraints(maxHeight: 1000), // **THIS is the important part**
        child: ListView.builder(
          shrinkWrap: true,
          itemBuilder: (context, index) => _buildRow(index),
          itemCount: _elements.length,
        ),
      ),
    ],
  ),
),
Freddyfredek answered 26/6, 2019 at 12:44 Comment(0)
H
8

In my case, adding physics: ScrollPhysics(), in the ListView.builder made the ListView.builder scrollable.

The hierarchy was ListView > StreamBuilder > RefreshIndicator > ListView.builder .

Headgear answered 14/10, 2020 at 9:22 Comment(0)
B
7

It actually depends on your layout. Possible cases could be:

  • Using ListView + ListView:

    If you want to give your second ListView full height.

    ListView(
      children: [
        // Your other widgets ...
        ListView.builder(
          shrinkWrap: true, //    <-- Set this to true
          physics: ScrollPhysics(), // <-- Also change physics
          itemBuilder: ...,
        ),
      ],
    )
    
  • Using ListView + ListView:

    If you want to limit the height of your second ListView.

    ListView(
      children: [
        // Your other widgets ...
        SizedBox( //             <-- Use SizedBox
          height: 160, 
          child: ListView.builder(
            itemBuilder: ...,
          ),
        ),
        // Your other widgets ...
      ],
    )
    
  • Using Column + ListView:

    If you don't have too many (or too big) children in your first ListView, replace it with a Column.

    Column(
      children: [
        // Your other widgets ...
        Expanded( //              <-- Use Expanded
          child: ListView.builder(
            itemBuilder: ...,
          ),
        ),
      ],
    )
    
Bonina answered 8/11, 2021 at 22:23 Comment(0)
L
4

I was able to solve the problem by wrapping main column inside a SingleChildScrollView, then wrapping the ListView.builder inside a Container giving container a specified height, and then wrapping that container inside a SingleChildScrollView again. I know it's a but complex, but it worked for me! you can have a clear picture by the code.

 Scaffold(
    appBar: AppBar(
      centerTitle: true,
      backgroundColor: Colors.black,
      title: Text("Welcome, ${widget.myUser.name}"),
      actions: [
        InkWell(
          child: Container(
            alignment: Alignment.center,
            padding: EdgeInsets.only(right: 20),
            child: Icon(Icons.settings),
          ),
          onTap: () {},
        ),
      ],
    ),
    body: Padding(
      padding: EdgeInsets.symmetric(horizontal: 20),
      child: SingleChildScrollView(
        child: Column(
          mainAxisSize: MainAxisSize.max,
          children: [
            _customerDetailsWidget(),
            SizedBox(
              height: 15,
            ),
            Container(
              child: Divider(
                color: Colors.grey[500],
              ),
            ),
            SizedBox(
              height: 15,
            ),
            _addProductText(),
            SingleChildScrollView(
                child: Container(
                  height: 500,
                  child: ListView.builder(
                    itemCount:1,
                    itemBuilder: (BuildContext context, int index) {
                      return Container(child: Text("HELLO WORLD"));
                    },
                  ),
                ))
          ],
        ),
      ),
    ),
  ),
Lipstick answered 1/9, 2020 at 15:19 Comment(1)
Thank you. I additional add SingleChildScrollView in ListView.build set shrinkWrap value to true.Impoverished
R
0
ListView.builder(
  physics: ScrollPhysics(),

  itemCount: question.questionByPage.value.data.length,

  shrinkWrap: true,

  primary: false,

  itemBuilder: (context, index) => ListView.builder(

    physics: ScrollPhysics(),

    shrinkWrap: true,

    itemCount: question.questionByPage.value

        .data[index].questions.length,

    itemBuilder: (BuildContext context, int qIndex) {

      var mydata = question.questionByPage.value

          .data[index].questions[qIndex];

      return ListView.builder(

        physics: ScrollPhysics(),

        shrinkWrap: true,

        itemCount: mydata.options.length,

        itemBuilder: (BuildContext context, int oIndex) {

          var option = mydata.options[oIndex];

          return Column(
       
            crossAxisAlignment: CrossAxisAlignment.start,

            children: [
           

              Text(
                mydata.description.toString(),

                textAlign: TextAlign.left,

              ),
              Text(

                option.optionText.toString(),

                textAlign: TextAlign.left,
              ),

            ],
          );
        },
      );
    },
  ),
),
Riven answered 9/2, 2023 at 4:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.