Search code examples
flutterlistviewflutter-layouthorizontal-scrollingvertical-scrolling

Horizontal ListView inside a Vertical ScrollView in Flutter


I am trying to achieve a very common behavior nowadays which is to have a horizontal List within another widget that is at the same time scrollable. Think something like the home screen of the IMDb app:

enter image description here

So I want to have a widget that scrolls vertically with few items on them. At the top of it, there should be a horizontal ListView, followed up with some items called motivationCard. There are some headers in between the list and the cards as well.

I got something like this on my Widget:

@override
  Widget build(BuildContext context) => BlocBuilder<HomeEvent, HomeState>(
        bloc: _homeBloc,
        builder: (BuildContext context, HomeState state) => Scaffold(
              appBar: AppBar(),
              body: Column(
                children: <Widget>[
                  Text(
                    Strings.dailyTasks,
                  ),
                  ListView.builder(
                    scrollDirection: Axis.horizontal,
                    itemCount: tasks.length,
                    itemBuilder: (BuildContext context, int index) =>
                        taskCard(
                          taskNumber: index + 1,
                          taskTotal: tasks.length,
                          task: tasks[index],
                        ),
                  ),
                  Text(
                    Strings.motivations,
                  ),
                  motivationCard(
                    motivation: Motivation(
                        title: 'Motivation 1',
                        description:
                        'this is a description of the motivation'),
                  ),
                  motivationCard(
                    motivation: Motivation(
                        title: 'Motivation 2',
                        description:
                        'this is a description of the motivation'),
                  ),
                  motivationCard(
                    motivation: Motivation(
                        title: 'Motivation 3',
                        description:
                        'this is a description of the motivation'),
                  ),
                ],
              ),
            ),
      );

this is the error I get:

I/flutter (23780): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (23780): The following assertion was thrown during performResize():
I/flutter (23780): Horizontal viewport was given unbounded height.
I/flutter (23780): Viewports expand in the cross axis to fill their container and constrain their children to match
I/flutter (23780): their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of
I/flutter (23780): vertical space in which to expand.

I have tried:

  • Wrapping the ListView with an Expanded widget

  • Wrapping the Column with SingleChildScrollView > ConstrainedBox > IntrinsicHeight

  • Having CustomScrollView as a parent, with a SliverList and the List within a SliverChildListDelegate

None of these work and I continue getting the same kind of error. This is a very common thing and shouldn't be any hard, somehow I just cannot get it to work :(

Any help would be much appreciated, thanks!

Edit:

I thought this could help me but it didn't.


Solution

  • Well, Your Code Work Fine with wrapping your- ListView.builder with Expanded Widget & setting mainAxisSize: MainAxisSize.min, of Column Widget.

    E.x Code of what you Have.

     body: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Text(
                'Headline',
                style: TextStyle(fontSize: 18),
              ),
              Expanded(
                child: ListView.builder(
                  shrinkWrap: true,
                  scrollDirection: Axis.horizontal,
                  itemCount: 15,
                  itemBuilder: (BuildContext context, int index) => Card(
                        child: Center(child: Text('Dummy Card Text')),
                      ),
                ),
              ),
              Text(
                'Demo Headline 2',
                style: TextStyle(fontSize: 18),
              ),
              Expanded(
                child: ListView.builder(
                  shrinkWrap: true,
                  itemBuilder: (ctx,int){
                    return Card(
                      child: ListTile(
                          title: Text('Motivation $int'),
                          subtitle: Text('this is a description of the motivation')),
                    );
                  },
                ),
              ),
            ],
          ),
    

    enter image description here

    Update:

    Whole page Is Scroll-able with - SingleChildScrollView.

    body: SingleChildScrollView(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(
            'Headline',
            style: TextStyle(fontSize: 18),
          ),
          SizedBox(
            height: 200.0,
            child: ListView.builder(
              physics: ClampingScrollPhysics(),
              shrinkWrap: true,
              scrollDirection: Axis.horizontal,
              itemCount: 15,
              itemBuilder: (BuildContext context, int index) => Card(
                    child: Center(child: Text('Dummy Card Text')),
                  ),
            ),
          ),
          Text(
            'Demo Headline 2',
            style: TextStyle(fontSize: 18),
          ),
          Card(
            child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
          ),
          Card(
            child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
          ),
          Card(
            child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
          ),
          Card(
            child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
          ),
          Card(
            child: ListTile(title: Text('Motivation $int'), subtitle: Text('this is a description of the motivation')),
          ),
        ],
      ),
    ),
    

    enter image description here