24

How can we implement Separator/Divider in SliverList. ListView.separated is handy way to create separators in list but i do not see any docs or examples about SliverList

inval
  • 380
  • 1
  • 4
  • 11

5 Answers5

50

Similar as ListView.separated

  import 'dart:math' as math;

  List<String> values = List();
  for (int i = 1; i <= 50; i++) {
    values.add(i.toString());
  }

  return CustomScrollView(
    semanticChildCount: values.length,
    slivers: <Widget>[
      SliverList(
        delegate: SliverChildBuilderDelegate(
          (BuildContext context, int index) {
            final int itemIndex = index ~/ 2;
            if (index.isEven) {
              return Padding(
                  child: Text(values[itemIndex]),
                  padding: EdgeInsets.all(16));
            }
            return Divider(height: 0, color: Colors.grey);
          },
          semanticIndexCallback: (Widget widget, int localIndex) {
            if (localIndex.isEven) {
              return localIndex ~/ 2;
            }
            return null;
          },
          childCount: math.max(0, values.length * 2 - 1),
        ),
      ),
    ],
  );
Carlos Eduardo
  • 740
  • 6
  • 10
  • ok this code works, and thanks btw, but i dont understand most of it, as in, first, why the divide by 2 and check for even, am just lost, i would appreciate if you just briefly explain what's going on here – lulliezy Feb 17 '21 at 22:01
  • 1
    Because SliverChildBuilderDelegate is building an extra widget (Divider) for each item. You can see the original list (values) with 50 items. Now you need build one extra Divider for each item ignoring the last one (more 49 dividers): values.length * 2 - 1. Your original list [item1, item2, item3] will became [item1, divider, item2, divider, item3] for example. In the build, you check if the new index represents an item or divider: [0 - item1 - even, 1 - divider - odd, 2 - item2 - even, 3 - divider - odd, 4 - item3 - even] – Carlos Eduardo Feb 19 '21 at 11:29
  • 1
    Of course, you could ignore it all and build a single Widget by adding the divider using a Column. You should only be concerned with the last one on the list, or not... – Carlos Eduardo Feb 19 '21 at 11:30
11

Simple ways,

Using SliverFillRemaining

return CustomScrollView(
    slivers: <Widget>[
      SliverFillRemaining(
        child: ListView.separated(
            itemCount:value.length,
            //shrinkWrap: true,
            physics: NeverScrollableScrollPhysics(),
            //padding: EdgeInsets.all(0),
            separatorBuilder: (BuildContext context, int index){
              return Divider();
            },
            itemBuilder: (BuildContext context, int index) {
              //widget return
            })
      ),

Using SliverList

 SliverList(
            delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                return Column(
                  children: <Widget>[
                    SizedBox(height: 5),
                    //your main widget is here
                    SizedBox(height: 5),
                    Divider(height: 1)
                  ],
                );

              },
              childCount: model.length,
            ),
          )
BIS Tech
  • 17,000
  • 12
  • 99
  • 148
  • 7
    Just as a note: Please dont use the first approach unless you have no other way. This will render all your children all by at once which can lead to huge memory problem and a horrible UX – Christian X Nov 06 '20 at 14:59
  • @ChristianX doesn't ```shrinkWrap: true``` try to render all the items in the list, even when not in viewport? Doesn't this cancel out the effect of ```SliverFillremaining```. – Nithin Sai Dec 01 '21 at 16:10
  • hmm I dont think so, because sliverfillremaining will simply just give the list a fixed height afaik. May be wrong, have worked with this widget for a while now – Christian X Dec 02 '21 at 09:59
  • *havent worked... – Christian X Dec 02 '21 at 13:26
  • Thank you for the SliverFillRemaining hack. – Sergio Tskhovrebov Feb 05 '23 at 17:04
6

Although this question is very old, I will add my answer for future readers. You simply wrap your widget with a Container and then you give the container a bottom border. Here is an example:

Container(
    decoration: BoxDecoration(
        border: Border(
            bottom: BorderSide(color: Colors.grey.shade300, width: 0.5))),
    child: YourWidget(),
  ),
rusted brain
  • 1,052
  • 10
  • 23
2

If you are wondering how to show Divider but not show on the last item. Try this.

Wrap your widget into Column then give a conditional for building Divider. The Divider Widget will show except on the last index. Example:

CustomScrollView(
  slivers: <Widget>[
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (_, int index) {
          return Column(
            children: <Widget>[
              // Put your widget here
              YourWidget(),

              // This divider will not appears on last index
              if(index != (item.length - 1))
                const Divider(),
            ],
          );
        },
        childCount: item.length,
      ),
    ),
  ],
),
Septian Dika
  • 446
  • 5
  • 17
-11

You can use the Divider() Widget.

Here you can find the documentation.

C.Pietro
  • 89
  • 1
  • 9