自定义滚动视图在 Sliver Persistent Header 下滚动

Posted

技术标签:

【中文标题】自定义滚动视图在 Sliver Persistent Header 下滚动【英文标题】:Custom Scroll View getting scrolled under Sliver Persistent Header 【发布时间】:2020-10-14 07:39:06 【问题描述】:
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 在 sliverPersistentHeader 选项卡下滚动。 DefaultTabController

嵌套滚动视图 SliverAppBar SliverPersistentHeader -body:自定义滚动视图 - 条子:SliverChildBuilderDelegate

SliverPersistentHeader 的所有选项卡都显示在顶部(TabBar)

Nested ScrollView 的主体是 CustomScrollView 其中有 SliverChildBuilderDelegate 有一个孩子。

在滚动列表时,我的列表滚动到 sliver 持久标题的选项卡后面。好像 sliverPersistentHeader 是透明的,后面可以看到列表滚动。

为了解决这个问题,我尝试了 SliverOverlapInjector 和 SliverOverlapAbsorber,但没有帮助。

CustomScrollView 滚动问题图片是第 4 位以便更好地理解。向日葵油卡片滚动到标签栏后面。

图片:

Sliver Overlap Absorber

Sliver Overlap Injector

Custom Scroll View

Overlapping Problem

【问题讨论】:

为什么选择SliverOverlapInjector / SliverOverlapAbsorber?你想达到什么目标? 我的列表在标签上滚动,我想删除这个效果。我分享了与此图片相关的图片 4。滚动到达标签下方的葵花籽油。 为什么不能只使用CustomScrollView 我试过了,但这个重叠问题仍然存在 我曾使用 SliverOverlapInjector/ SliverOverlapAbsorber 来消除这种重叠效果,但不起作用 【参考方案1】:
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;
  

不是只从 SliverPersistentHeaderDelegate 返回 TabBar Widget,而是用 Container 包装它并设置 backgroundColor 来解决我的问题。

在类 _ProductTabSliver 构建方法中我已经包装了容器

【讨论】:

哇!有用!谢谢!我有 NestedScrollView,里面有 CustomScrollView。我的 headerSliv​​erBuilder 没有滚动,直到我将 CustomScrollView 包装在容器中谢谢你!

以上是关于自定义滚动视图在 Sliver Persistent Header 下滚动的主要内容,如果未能解决你的问题,请参考以下文章

自定义视图在滚动视图内滚动

onDraw 滚动视图中的自定义视图

自定义滚动谷歌颤动中的水平列表视图

在Flutter中创建有意思的滚动效果 - Sliver系列

UITableView 中滚动的自定义视图

具有自定义视图的 NSMenuItem 在滚动时消失