Search code examples
flutterflutter-sliver

When scrolling first page in NestedScrollView the second page will be scrolled underneath SliverPersistentHeader as well


I have NestedScrollView as such:

headers: [
  SliverToBox(), // This scrolls away
  SliverPersistentHeader(), // This needs to pin
]
body: TabBarView() // Classic TabBar view with multiple pages

This is how it looks unscrolled:

enter image description here

This is how it looks when I start scrolling 1st page (all good so far):

enter image description here

And this is how it looks when I swipe to the next tab. Notice that the next page is already scrolled a little bit (starts from 2 and it should start from 0). The difference is in height of PersistentSliverHeader, basically second page gets scrolled underneath the header. How can I make the scroll on page 1 not affect the scroll on page 2?

enter image description here

Code: Here is the Gist, unfortunately it doesn't work on web/dartpad but on mobile runs without issues: https://gist.github.com/itsJoKr/eca5b57c2f290f517862dcd118a16d4d


Solution

  • Answer was to use SliverOverlapAbsorber.

                  SliverOverlapAbsorber(
                    handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                    sliver: SliverPersistentHeader(
                      pinned: true,
                      delegate: ChipTabBarSliverDelegate2(
                        tabController,
                        [
                          'tab 1',
                          'tab 2',
                          'tab 3',
                        ],
                        MediaQuery.of(context).padding.top,
                      ),
                    ),
                  ),
    

    And key this is handle. It's exactly for this as it says in the docs:

      // This widget takes the overlapping behavior of the SliverAppBar,
      // and redirects it to the SliverOverlapInjector below. If it is
      // missing, then it is possible for the nested "inner" scroll view
      // below to end up under the SliverAppBar even when the inner
      // scroll view thinks it has not been scrolled.
      // This is not necessary if the "headerSliverBuilder" only builds
      // widgets that do not overlap the next sliver.