Custom Scroll View getting scrolled under Sliver Persistent Header

3,827
class ProductAppBar extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
  
    return NestedScrollView(
      physics: BouncingScrollPhysics(),
      headerSliverBuilder: (headerCtx, innnerBoxIsScrolled) {
        return <Widget>[
          SliverAppBar(
            expandedHeight: 200.0,
            backgroundColor: _productColor.backgroundColor,
            pinned: true,
            elevation: 0,
            forceElevated: innnerBoxIsScrolled,
            flexibleSpace: FlexibleSpaceBar(
              title: Text("${_subCategory.currentSubCategoryName()}"),
              background: Container(
                margin: const EdgeInsets.only(
                  top: 4,
                  bottom: 50.0,
                ),
                child: Hero(
                  tag: _subCategory.currentSubCategoryId(),
                  child: Image.asset(
                    'asset/images/grocery.jpeg',
                  ),
                ),
              ),
            ),
          ),
          SliverOverlapAbsorber(
            handle: NestedScrollView.sliverOverlapAbsorberHandleFor(headerCtx),
            sliver: SliverPersistentHeader(
              pinned: true,
              delegate: _ProductTabSliver(
                TabBar(
                  onTap: (index) {
                    _subCategory.updateTabIndex(index);
                  },
                  labelColor: Colors.white,
                  unselectedLabelColor: Colors.black87,
                  tabs: [
                    ..._subCategory.currentTab().map(
                      (tabValue) {
                        return Tab(text: "${tabValue.fullName}");
                      },
                    ).toList()
                  ],
                ),
              ),
            ),
          ),
        ];
      },
      body: TabBarView(
        children: _subCategory.currentTab().map((tabElement) {
          return ProductScreenLayout();
        }).toList(),
      ),
    );
  }
}

class _ProductTabSliver extends SliverPersistentHeaderDelegate {
  final TabBar _tabBar;

  _ProductTabSliver(this._tabBar);

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    final _productColor =
        Provider.of<ColorConfig>(context, listen: false).randomProductColor();

    return Container(
        decoration: BoxDecoration(
          color: _productColor.backgroundColor,
        ),
        child: _tabBar);
  }

  @override
  double get maxExtent => _tabBar.preferredSize.height;

  @override
  double get minExtent => _tabBar.preferredSize.height;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}

Instead of returning just TabBar Widget from the SliverPersistentHeaderDelegate wrapping it with Container and setting backgroundColor solve my problem.

Inside class _ProductTabSliver build method I had wrapped the Container

Share:
3,827
Himanshu Rajput
Author by

Himanshu Rajput

Updated on December 03, 2022

Comments

  • Himanshu Rajput
    Himanshu Rajput over 1 year
    DefaultTabController(
              length: _subCategory.tabLength,
              initialIndex: 0,
              child:
    NestedScrollView(
          physics: BouncingScrollPhysics(),
          headerSliverBuilder: (headerCtx, innnerBoxIsScrolled) {
            return <Widget>[
              SliverAppBar(
                expandedHeight: 200.0,
                backgroundColor: _productColor.backgroundColor,
                pinned: true,
                elevation: 0,
                forceElevated: innnerBoxIsScrolled,
                flexibleSpace: FlexibleSpaceBar(
                  title: Text("${_subCategory.currentSubCategoryName()}"),
                  background: Container(
                    margin: const EdgeInsets.only(
                      top: 4,
                      bottom: 50.0,
                    ),
                    child: Hero(
                      tag: _subCategory.currentSubCategoryId(),
                      child: Image.asset(
                        'asset/images/grocery.jpeg',
                      ),
                    ),
                  ),
                ),
              ),
              SliverOverlapAbsorber(
                handle: NestedScrollView.sliverOverlapAbsorberHandleFor(headerCtx),
                sliver: SliverPersistentHeader(
                  pinned: true,
                  delegate: _ProductTabSliver(
                    TabBar(
                      labelColor: Colors.white,
                      unselectedLabelColor: Colors.black87,
                      tabs: [
                        ..._subCategory.currentTab().map(
                          (tabValue) {
                            return Tab(text: "${tabValue.fullName}");
                          },
                        ).toList()
                      ],
                    ),
                  ),
                ),
              ),
            ];
          },
          body:CustomScrollView(
          physics: BouncingScrollPhysics(),
          slivers: <Widget>[
            SliverOverlapInjector(
              handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
            ),
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (ctx, pdIndex) {
                  final heightVisible =
                      _subCategory.advanceCompanyProductCount(pdIndex);
               
               return ProductLayout();
     },
                childCount: _subCategory.differentProductCount(),
              ),
            ),
          ],
        );,
        ));
    

    CustomScrollList getting scrolled under sliverPersistentHeader Tab. DefaultTabController

    • NestedScrollView
      • SliverAppBar
      • SliverPersistentHeader -body: CustomScrollView - slivers: SliverChildBuilderDelegate

    SliverPersistentHeader had all the tabs displayed on the top(TabBar)

    Body of Nested ScrollView is CustomScrollView which has SliverChildBuilderDelegate has a child.

    On scrolling the list, my list scroll behind the tabs of sliver persistent header. Seems like sliverPersistentHeader is transparent and list scrolls can be seen behind.

    To solve this problem, I had tried SliverOverlapInjector and SliverOverlapAbsorber, but that didn't help.

    CustomScrollView scroll problem image is 4th for better understanding. Sunflower oil card on scrolling reaches behind the tab bar.

    Images:

    Sliver Overlap Absorber

    Sliver Overlap Injector

    Custom Scroll View

    Overlapping Problem

    • pskink
      pskink almost 4 years
      and why rhose SliverOverlapInjector / SliverOverlapAbsorber? what do you want to achieve?
    • Himanshu Rajput
      Himanshu Rajput almost 4 years
      My List is getting scroll over the tabs and I want to remove this effect . I had share image related to this image no 4. Sunflower oil on scrolling reach below the tabs.
    • pskink
      pskink almost 4 years
      why cannot you just use CustomScrollView?
    • Himanshu Rajput
      Himanshu Rajput almost 4 years
      I had tried but then also this overlapping problem remains
    • Himanshu Rajput
      Himanshu Rajput almost 4 years
      I had used SliverOverlapInjector/ SliverOverlapAbsorber to remove this overlapping effect but not working
    • Himanshu Rajput
      Himanshu Rajput almost 4 years
      I had read this article github.com/flutter/flutter/issues/21551
  • Ya Si
    Ya Si over 3 years
    Wow! It works! Thank you! I have NestedScrollView and inside it CustomScrollView. My headerSliverBuilder was not scrolled until I wrapped CustomScrollView in Container Thank u!