首页 > 解决方案 > 嵌套滚动条问题:NestedScrollView、SliverAppBar、SliverPersistentHeader、TabBarView 和 PageView

问题描述

这个问题一直困扰着我一段时间,即使我阅读了无数的网页,我仍然无法解决它。也许你能帮上忙!

我得到了以下场景:

Flutter 应用程序PageView只有 3 个页面。

第一页有一个简单的GridView(垂直滚动),嵌套滚动没有问题。

第三页是一个简单ListView的项目列表,滚动也没有问题。

第二个页面有一个NestedScrollView, 有两个小部件用于它的headerSliverBuilder:SliverAppBarSliverPersistentHeader. 这里没有什么花哨的。

正文NestedScrollView包含TabBarView3 个选项卡,并且可以使用水平滑动在它们之间滑动 - 与PageView包含此页面的滑动方向相同。

正文是发生滚动问题的地方。

在 3 个标签之间滑动就像一个魅力。但是,当当前选项卡是第一个选项卡并且您尝试进一步向左滑动(手指运动是从左到右)时,第一页(属于PageView)不会显示。相反,当当前选项卡是第三个并且您尝试进一步向右滑动(手指运动是从右到左)时,没有任何反应。

如果您在第二页中包含的页眉上执行相同的手指动作,则页面会很好地转动(到第一页或第三页)。

这是第二页中的代码,很想知道为什么TabBarView当标签到达边缘时,内部的滑动动作不会传播到容器:

Scaffold(
  appBar: _generateAppBar(),
  body: DefaultTabController(
    length: 3,
    child: NestedScrollView(
      headerSliverBuilder: (_, __) => [
        SliverAppBar(
          backgroundColor: backgroundColor,
          elevation: 0.0,
          expandedHeight: 200.0,
          floating: true,
          pinned: false,
          flexibleSpace: backgroundImageView,
        ),
        SliverPersistentHeader(
          floating: false,
          delegate: _SliverAppBarDelegate(
            TabBar(
              labelColor: Theme.of(context).primaryColor,
              unselectedLabelColor: Colors.black26,
              indicatorWeight: 2.5,
              tabs: const [
                Text('Tab 1'),
                Text('Tab 2'),
                Text('Tab 3'),
              ],
            ),
          ),
          pinned: true,
        ),
      ],
      body: TabBarView(
        children: [
          Center(child: Text('Body 1')),
          Center(child: Text('Body 2')),
          Center(child: Text('Body 3')),
        ],
      ),
    ),
  ),
);

辅助类:

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate(this._tabBar);

  final TabBar _tabBar;

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

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

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) =>
    Container(child: _tabBar);

  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) =>
    false;
}

知道如何解决这个问题吗?谢谢!

标签: flutterflutter-sliver

解决方案


你应该包装 NestedScrollView喜欢

DefaultTabController(
      length: tabs.length,
      child: NestedScrollView())

推荐阅读