V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
alvazu
V2EX  ›  程序员

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

  •  
  •   alvazu · 2021-11-13 23:49:04 +08:00 · 486 次点击
    这是一个创建于 958 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 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(),
              ),
            ),
          ),
        );
      }
    }
    
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2371 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 05:28 · PVG 13:28 · LAX 22:28 · JFK 01:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.