求助,关于 Flutter 的 NestedScrollView 与 Scrollbar 冲突

2021-11-13 23:49:04 +08:00
 alvazu

在 Stackoverflow 上找了一圈也没有找到答案,想向 v2 的朋友们求助一下。

NestedScrollView + SliverAppBar + TabViewScrollbar合用,在左右滑动时出现以下错误:

The following assertion was thrown while notifying status listeners for AnimationController: The PrimaryScrollController is currently attached to more than one ScrollPosition.

我尝试过用PrimaryScrollController包裹Scroller 组件,错误不再出现,但是NestedScrollView上下两边的滚动不再同步;尝试过写NotificationListener,问题看起来解决了,但是会有奇怪的卡顿现象:

NotificationListener<ScrollNotification>(
            onNotification: (ScrollNotification notification) {
              //print(notification.metrics.axisDirection);
              if (notification.metrics.extentAfter > 0 &&
                  notification.metrics.extentBefore > 0 &&
                  notification.metrics.axisDirection == AxisDirection.down) {
                double pixelnow = notification.metrics.pixels;
                double _jmpTo =
                    _scrollController.offset + (pixelnow - _scrollLocation);
                //print("pixel now : $pixelnow");
                //print("jumpto: $_jmpTo");
                if (_scrollController.position.maxScrollExtent >= _scrollController.offset 
                  && _scrollController.offset >= _scrollController.position.minScrollExtent ){
                  _scrollController.jumpTo(_jmpTo);
                  //_scrollController.jumpTo(value)
                }
                _scrollLocation = pixelnow;
              }
              return false;
            },

我的原始代码如下:


import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: Scaffold(body: CommunityPage())));

class CommunityPage extends StatefulWidget {
  CommunityPage({Key? key}) : super(key: key);

  @override
  _CommunityPageState createState() => _CommunityPageState();
}

class _CommunityPageState extends State<CommunityPage> {
  //ScrollController _scrollController = ScrollController();
  //final TabController _tabController = TabController();
  final _tabs = <String>["Tab 1", "Tab 2", "Tab 3"];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: _tabs.length, // This is the number of tabs.
        child: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            // These are the slivers that show up in the "outer" scroll view.
            return <Widget>[
              SliverOverlapAbsorber(
                handle:
                    NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                sliver: SliverAppBar(
                  automaticallyImplyLeading: false,
                  title: const Text("Community",style: TextStyle(color: Colors.black)),
                  //centerTitle: false,
                  pinned: true,
                  floating: true,
                  snap: true,
                  backgroundColor: Colors.grey[50],
                  expandedHeight: 85.0,

                  bottom: TabBar(
                    tabs: _tabs.map((String name) => Tab(text: name)).toList(),
                  ),
                ),
              ),
            ];
          },
          body: TabBarView(
            children: _tabs.map((String name) {
              //SafeArea 适配刘海屏的一个 widget
              return Builder(
                builder: (BuildContext context) {
                  return Scrollbar(
                    child: CustomScrollView(
                      key: PageStorageKey<String>(name),
                      slivers: <Widget>[
                        SliverOverlapInjector(
                          handle:
                              NestedScrollView.sliverOverlapAbsorberHandleFor(
                                  context),
                        ),
                        SliverFixedExtentList(
                          itemExtent: 50.0, //item 高度或宽度,取决于滑动方向
                          delegate: SliverChildBuilderDelegate(
                            (BuildContext context, int index) {
                              return ListTile(
                                title: Text('Item $index'),
                              );
                            },
                            childCount: 30,
                          ),
                        ),
                      ],
                    ),
                  );
                },
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}
487 次点击
所在节点    程序员
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/815213

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX