Horizontal ListView inside a Vertical ScrollView in Flutter

In this blog post, we will explore how to implement a horizontal ListView inside a vertical ScrollView in Flutter. This is a common scenario when you have a lot of content that needs to be displayed horizontally within a scrolling container.

The Problem

When you try to nest a ListView inside another Scrollable widget (such as a ScrollView or a Column with Expanded), it will not work as expected. This is because both the outer and inner ListView are trying to scroll their children, resulting in an ambiguous scrolling behavior.

The Solution

One way to solve this problem is by wrapping your ListView.builder with an Expanded widget and setting mainAxisSize: MainAxisSize.min of Column widget. This will ensure that the inner ListView scrolls horizontally within its parent Column, while the outer ScrollView or Column still scrolls vertically.

body: Column(
  mainAxisSize: MainAxisSize.min,
  children: [
    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'),
            ),
          );
        },
      ),
    ),
  ],
),

Another way to solve this problem is by using a SingleChildScrollView widget as the outermost container. This will ensure that the entire page scrolls vertically, while the inner ListView scrolls horizontally within its parent Column.

body: SingleChildScrollView(
  child: Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      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')),
      ),
    ],
  ),
),

Example Code

Here is an example code snippet that demonstrates how to implement a horizontal ListView inside a vertical ScrollView in Flutter:

class _HomePageState extends State {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: 7,
        itemBuilder: (_, i) {
          if (i < 2)
            return _buildBox(color: Colors.blue);
          else if (i == 3)
            return _horizontalListView();
          else
            return _buildBox(color: Colors.blue);
        },
      ),
    );
  }

  Widget _horizontalListView() {
    return SizedBox(
      height: 120,
      child: ListView.builder(
        scrollDirection: Axis.horizontal,
        itemBuilder: (_, __) => _buildBox(color: Colors.orange),
      ),
    );
  }

  Widget _buildBox({Color color}) => Container(margin: EdgeInsets.all(12), height: 100, width: 200, color: color);
}

Conclusion

In this blog post, we explored how to implement a horizontal ListView inside a vertical ScrollView in Flutter. We discussed two different approaches to solving this problem and provided example code snippets to demonstrate each approach. By using Expanded widgets or SingleChildScrollView as the outermost container, you can create a scrolling layout that includes both vertical and horizontal ListViews.