Is it possible to use ListView.builder inside of CustomScrollView?
Asked Answered
H

5

27

Is it possible to use ListView.builder (or something similar) inside of a CustomScrollView? I have a CustomScrollView like this:

return Scaffold(
  body: CustomScrollView(
    slivers: [
      SliverAppBar(...),
      SliverList(delegate: SliverChildListDelegate(children))
    ],
  ),
);

This works great, but in my actual scenario the list could have thousands of items, so I do not want to pass them all in to SliverChildListDelegate. I want to use ListView.builder (or something similar) to build the items as they are scrolled into view. I was expecting there to be a .builder constructor on either SliverList or SliverChildListDelegate but I don't see anything like that. Am I missing something?

Heteropolar answered 3/3, 2019 at 21:30 Comment(0)
C
34

The delegate argument of SliverList is not necessarily a SliverChildListDelegate.

You can also use SliverChildBuilderDelegate to achieve the builder effect of ListView.builder

SliverList(delegate: SliverChildBuilderDelegate((context, index) {
  return Container();
}));
Cassimere answered 3/3, 2019 at 22:18 Comment(2)
I am using SilverBuilderDelegate but still scrolling not working. I have raised a questions. #62437549Fiddler
The child count needs to be added... so delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ...; }, childCount: ...length, ),Cognate
G
34

I'm not sure how it is done in CustomScrollView but you can try this:

Scaffold(
      body: NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverAppBar(...),
          ];
        },
        body: ListView.builder(..),)
);
Gruchot answered 3/3, 2019 at 21:55 Comment(1)
You made my day. I struggled to convert ListView into Slivers to hide the page title when scrolling until I found your solution using NestedScrollView with headerSliverBuilder. Thank you very much.Lintel
C
34

The delegate argument of SliverList is not necessarily a SliverChildListDelegate.

You can also use SliverChildBuilderDelegate to achieve the builder effect of ListView.builder

SliverList(delegate: SliverChildBuilderDelegate((context, index) {
  return Container();
}));
Cassimere answered 3/3, 2019 at 22:18 Comment(2)
I am using SilverBuilderDelegate but still scrolling not working. I have raised a questions. #62437549Fiddler
The child count needs to be added... so delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ...; }, childCount: ...length, ),Cognate
W
8

You can use List.generate as example below

return Scaffold(
 body: CustomScrollView(
    slivers: [
      SliverAppBar(...),
      SliverList(delegate: SliverChildListDelegate(
          List.generate(yourList.length, (idx) {
                return Padding(
                  padding: const EdgeInsets.only(left: 8.0, right: 8.0),
                  child: Card(
                    child: ListTile(
                      leading: Icon(null),
                      title: Text(yourList[idx]),
                      onTap: null,
                    ),
                  ),
                );
              })
      ))
    ],
  ),
);
Welldressed answered 25/10, 2019 at 21:51 Comment(1)
In addition to the code you've provided, consider giving a summary as to why this solves the issue.Legman
C
2

This worked for me and I can have a SliverAppBar

return CustomScrollView(
      slivers: [
        SliverAppBar(
        ),
        SliverList(
            delegate: SliverChildListDelegate([
          SingleChildScrollView(
            child: Column(
              children: [
                Container(
                  child: ListView.builder(
                    shrinkWrap: true,
                    physics: NeverScrollableScrollPhysics(),
                    itemBuilder: (BuildContext context, int index) {

                    }
                  ),
                ),
              ],
            ),
          )
        ]))
      ],
    );
Chericheria answered 11/11, 2020 at 2:20 Comment(2)
using shrink wrap will have serious performance issues for huge lists. youtube.com/watch?v=LUqDNnv_dh0Hoebart
For everyone else coming here: You can safely use shrinkWrap: true if you have ~2-4 widgets to render, but i totally agree with Nithin Sai that it will drastically cause performance issues and possible memory issues (if you render e.g. many images).Buckeye
G
0

You can use SliverList.builder directly instead of ListView.builder. For instance:

return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverAppBar(...),
          SliverList.builder(
            itemCount: itemCount,
            itemBuilder: (context, index) {
              return YourItemWidget();
            },
          ),
        ],
      ),
    );
Guibert answered 23/2 at 9:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.