Search code examples
flutterdartflutter-sliver

How to achieve nested slivers? A sliver containing a list of slivers


SliverList is a sliver that contains box widgets. Is there a sliver that contains sliver widgets?

I am attempting to nest flutter_sticky_headers to create a timeline, but SliverStickyHeader only accepts a single sliver as an argument (see comment in monthSlivers()).

class HomeView extends StatelessWidget {
  final HomeViewModel viewModel;

  HomeView(this.viewModel);

  List<Widget> entryTiles(List<EntryTileViewModel> entryVMs) {
    return entryVMs.map((entryVM) => EntryTile(viewModel: entryVM)).toList();
  }

  List<Widget> daySlivers(List<DaySection> daySections) {
    return daySections.map((daySection) {
      var entries = entryTiles(daySection.entryVMs);
      return SliverStickyHeader(
        overlapsContent: true,
        header: DayHeader(
          viewModel: DayHeaderViewModel(date: daySection.date),
        ),
        sliver: SliverList(
          delegate: SliverChildBuilderDelegate(
                (context, i) => entries[i],
            childCount: entries.length,
          ),
        ),
      );
    }).toList();
  }

  List<Widget> monthSlivers() {
    return viewModel.monthSections.map((monthSection) {
      var days = daySlivers(monthSection.daySections);
      return SliverStickyHeader(
        header: MonthHeader(
          viewModel: MonthHeaderViewModel(date: monthSection.date),
        ),
        sliver:,// THIS IS WHERE I WANT TO PUT DAYSLIVERS().
      );
    }).toList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: CustomScrollView(
        slivers: monthSlivers(),
      ),
    );
  }
}

Solution

  • You can use the sliver_tools package. It has a widget called MultiSliver that your desired result could be achieved by this. As documentation mentioned :

    The MultiSliver widget allows for grouping of multiple slivers together such that they can be returned as a single widget. For instance when one wants to wrap a few slivers with some padding or an inherited widget.

    and this is an example :

    class WidgetThatReturnsASliver extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MultiSliver(
          children: <Widget>[
            SliverPersistentHeader(...),
            SliverList(...),
          ],
        );
      }
    }
    

    or you can use it inside a CustomScrollView :

    CustomScrollView(
      slivers:[
        MultiSliver(
          SliverList(...),
          SliverGrid(...),
          ...
        )
      ]
    )