Flutter: How to load items lazily when having two nested listview.builders?

Viewed 38

In my code I use nested listview.builder with shrinkWrap: true and NeverScrollableScrollPhysics(). The problem is that the items are not loaded lazily because they are nested in a SingleChildScrollView().

However I need a way to have two (or more) listview.builder among themselves with only the full screen to be scrollable.

@override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            buildListView(list1),
            buildListView(list2),
          ],
        ));
  }

  Widget buildListView(List list) {
    return ListView.builder(
      itemCount: list.length,
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      itemBuilder: (context, index) => ListTile(title: list[index].toString()),
    );
  }
1 Answers

You can use CustomScrollViews they are more flexible and powerful than SingleChildScrollViews. Also use Slivers instead ListViews.

CustomScrollView(
  slivers: [
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return ListTile(title: list1[index]);
        },
        childCount: list1.length,
      ),
    ),
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return ListTile(title: list2[index]);
        },
        childCount: list2.length,
      ),
    ),
  ],
);

You can also create the same build method for Slivers:

Widget build(BuildContext) {
  return CustomScrollView(
    slivers: [
      buildListView(list1),
      buildListView(list2),
    ],
  );
}

Widget buildListView(List list) {
  return SliverList(...);
}

All items will be lazy loaded and everything will be available in a single full-screen scrollable area.

See also SliverGrid.

Related