Flutter : ListView, GridView inside ScrollView

Sometimes you need to use a ListView or GridView inside a ScrollView (SingleChildScrollView). We know this isn’t a good practise as you can’t put a ListView being a Scrollable widget inside ScrollView, but for some reason i wanted to achieve this, especially when i want to show both ListView and GridView at the same time.

First of all, let’s see what happens when you put a ListView inside a SingleChildScrollView.

Create a new project and embed the following code:

return Scaffold(
appBar: AppBar(
title: Text("ListView"),
),
body: Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
HeaderWidget("Header 1"),
HeaderWidget("Header 2"),
HeaderWidget("Header 3"),
HeaderWidget("Header 4"),
ListView(
children: <Widget>[
BodyWidget(Colors.blue),
BodyWidget(Colors.red),
BodyWidget(Colors.green),
],
),
],
),
),
),
// This trailing comma makes auto-formatting nicer for build methods.
);

The HeaderWidget and BodyWidget are just simple widgets. (These are separated just to maintain the readability of the code)

class HeaderWidget extends StatelessWidget {
final String text;

HeaderWidget(this.text);

@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(16.0),
child: Text(text),
color: Colors.grey[200],
);
}
}

class BodyWidget extends StatelessWidget {
final Color color;

BodyWidget(this.color);

@override
Widget build(BuildContext context) {
return Container(
height: 100.0,
color: color,
alignment: Alignment.center,

);
}
}

If you run the above code, you get an exception in the console.

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY╞══════════════════════
I/flutter ( 3423): The following assertion was thrown during performResize():
I/flutter ( 3423): Vertical viewport was given unbounded height.
I/flutter ( 3423): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter ( 3423): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter ( 3423): typically happens when a scrollable widget is nested inside another scrollable widget.

I/flutter ( 3423): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter ( 3423): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter ( 3423): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter ( 3423): the height of the viewport to the sum of the heights of its children.

Note the bold text above.
The gist of which says that you can’t place an unbounded height widget (ListView, GridView) inside a Scrollable widget.

So how do we implement it?

Here we’ll be using Slivers to achieve this. Read more about slivers over here.

Replace the above code with the following code:

return Scaffold(
appBar: AppBar(
title: Text("ListView"),
),
body: 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),
],
),
),
],
),
),
);

In the above code:

1. We are replacing SingleChildScrollView with CustomScrollView.

2. Using SliverList in place of Column for showing HeaderWidget.

3. Finally using grid with SliverGrid.

Here’s the outcome of this:

Cool enough! We have both TextWidget, ListView, GridView inside that of ScrollView.

Note that your ListView, GridView must not have large number of children which can affect the scrolling performance as both of these widget do not inflate all children at the same time.

Whola! Both you and I learnt something new today. Congrats
Clap! Clap! Clap!

Further Reading:

  1. https://medium.com/flutter-io/slivers-demystified-6ff68ab0296f
  2. https://flutter.io/docs/development/ui/advanced/slivers

The Flutter Pub is a medium publication to bring you the latest and amazing resources such as articles, videos, codes, podcasts etc. about this great technology to teach you how to build beautiful apps with it. You can find us on Facebook, Twitter, and Medium or learn more about us here. We’d love to connect! And if you are a writer interested in writing for us, then you can do so through these guidelines.