flutterlistviewdart

ListView.builder inside another ListView.builder flutter


I have a ListView.builder that has a dropdown arrow to the right such that when its tapped, it shows another listView.builder with its items. The first list works well as it takes the size of its child items but the same experience is not happening on the second list. I have tried every solution but its still not working as I get an error.

Code

  Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              SizedBox(
                height: 30,
              ),
              Text(
                "SELECT A PACKAGE",
                textAlign: TextAlign.start,
                style: TextStyle(
                  fontSize: 12,
                  fontFamily: 'Lato',
                  color: textColor,
                  fontWeight: FontWeight.w700,
                ),
              ),
              SizedBox(
                height: 14,
              ),
              !isDataLoaded?ShimmerListView():
                  Expanded(
                    child: ListView.builder(
                      shrinkWrap: true,
                      physics: NeverScrollableScrollPhysics(),
                      itemCount: bloc.packages.length,
                      itemBuilder: (context, index){
                        return Container(
                          margin: EdgeInsets.only(bottom: 5),
                          child: Card(
                            shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.
                                all(Radius.circular(12)),
                                side: BorderSide(color:
                                borderColor, width: 1)
                            ),
                            child: Container(
                              padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
                              child:  Row(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Column(
                                    mainAxisSize: MainAxisSize.min,
                                    crossAxisAlignment: CrossAxisAlignment.start,
                                    children: [
                                      Text(
                                        bloc.packages[index].title,
                                        textAlign: TextAlign.start,
                                        style: TextStyle(
                                          fontSize: 16,
                                          fontFamily: 'Lato',
                                          color: primaryColor,
                                          fontWeight: FontWeight.w700,
                                        ),
                                      ),
                                      SizedBox(
                                        height: 14,
                                      ),
                                      Text(
                                        bloc.packages[index].desc,
                                        textAlign: TextAlign.start,
                                        style: TextStyle(
                                          fontSize: 14,
                                          fontFamily: 'Lato',
                                          color: textColor,
                                          fontWeight: FontWeight.w500,
                                        ),
                                      ),
                                      bloc.packages[index].isTapped?
                                      Container(
                                        height: 300,
                                        child: ListView.builder(
                                          physics: NeverScrollableScrollPhysics(),
                                          shrinkWrap: true,
                                          itemCount: bloc.packages[globalIndex].plans.length,
                                          itemBuilder: (context, index){
                                          return Container(
                                            width: 230,
                                            margin: EdgeInsets.only(top: 14),
                                            padding: EdgeInsets.symmetric
                                              (horizontal: 10, vertical: 10),
                                            decoration: BoxDecoration(
                                                color:containerBgColor,
                                                borderRadius: BorderRadius
                                                    .all(Radius.circular(12))
                                            ),
                                            child: Row(
                                              mainAxisSize: MainAxisSize.min,
                                              children: [
                                                Container(
                                                  width:24,
                                                  height:24,
                                                  decoration: BoxDecoration(
                                                    color: Colors.white,
                                                    shape: BoxShape.circle,
                                                  ),
                                                ),
                                                SizedBox(
                                                  width: 16,
                                                ),
                                                Column(
                                                  mainAxisSize: MainAxisSize.min,
                                                  crossAxisAlignment: CrossAxisAlignment.start,
                                                  children: [
                                                    Text(
                                                      bloc.packages[index].desc,
                                                      textAlign: TextAlign.start,
                                                      style: TextStyle(
                                                        fontSize: 14,
                                                        fontFamily: 'Lato',
                                                        color: textColor,
                                                        fontWeight: FontWeight.w500,
                                                      ),
                                                    ),
                                                    SizedBox(
                                                      height: 10,
                                                    ),
                                                    Text(
                                                      'NGN ${12000}',
                                                      textAlign: TextAlign.start,
                                                      style: TextStyle(
                                                        fontSize: 16,
                                                        fontFamily: 'Lato',
                                                        color: normalText,
                                                        fontWeight: FontWeight.w700,
                                                      ),
                                                    ),
                                                  ],
                                                ),
                                              ],
                                            ),
                                          );
                                          },
                                        ),
                                      )
                                          :Container(),
                                    ],
                                  ),
                                  Spacer(),
                                  IconButton(icon:
                                  Icon(
                                   !bloc.packages[index].isTapped?
                                   Mdi.chevronDown:
                                   Mdi.chevronUp,
                                    color: textColor,
                                  ), onPressed:(){
                                    setState(() {
                                      globalIndex = index;
                                      bloc.packages[index].isTapped
                                      = !bloc.packages[index].isTapped;
                                    });
                                  })
                                ],
                              ),
                            ),
                          ),
                        );
                      },
                    ),
                  ),
            ],
          ),

Error

RenderBox was not laid out: RenderRepaintBoundary#87e06 relayoutBoundary=up27 NEEDS-PAINT

Tried wrapping second list with an expanded and also give fixed height but got same error.


Solution

  • ListView requires a finite height, but your inner ListView has an infinite height.
    One way you can do it is to wrap the inner ListView with a Container, SizedBox, or any widget with a defined height

    example

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('title'),
        ),
        body: ListView.builder(
          itemCount: 20,
          itemBuilder: (BuildContext context, int index) {
            if (index == 10) {
              return Container(
                height: 200,  // finite height
                child: ListView.builder(
                  itemCount: 20,
                  itemBuilder: (BuildContext context, int index) {
                    return Container(
                      height: 30,
                      color: Color.fromRGBO(10, 255, index * 10, 100),
                      child: Text(index.toString()),
                    );
                  },
                ),
              );
            }
            return Container(
              height: 36,
              color: Color.fromRGBO(index * 10, 20, 100, 100),
              child: Text(index.toString()),
            );
          },
        ),
      );
    }
    

    if you want a cleaner way check out the NestedScrollView, and this answer to a similar question.


    Edit: 'constraints.hasBoundedWidth': is not true. error

    you need to provide a finite width for ListView. your ListView is in a row, which has an infinite width.

    to fix it, edit the row in line 39 as follows.

    Row(
      children: [
        Expanded( // 1- Wrap the Column with an Expanded
          child: Column(
            // ...
          ),
        ),
        // Spacer(), 2- Remove Spacer
        IconButton(
          // ...
        ),
      ],
    )