【问题标题】:ScrollController not attached to any scroll viewsScrollController 未附加到任何滚动视图
【发布时间】:2019-02-06 10:22:16
【问题描述】:

我正在使用 CustomScrollView,并为它提供了一个控制器。 ScrollController 有效,我什至给它添加了一个监听器并打印出滚动视图的位置。

CustomScrollView(
    controller: _scrollController,

现在,我要做的就是跳转到 initState() 函数中的位置 50.0。

_scrollController.jumpTo(50.0);

但是,我得到了错误

scrollController 未附加到任何滚动视图

【问题讨论】:

  • 请发布更多代码。你在哪里打电话jumpTo?不允许你用initState或类似的方式来做。
  • @boformer 是的,正如我在问题中提到的那样,我在 initState 中调用它,文档没有提到任何关于不在 initState 中调用它的内容。
  • 我也试过了。它不起作用,因为控制器仅在运行 build 方法并且滚动视图附加到树后附加。

标签: flutter


【解决方案1】:

推迟它不是正确的解决方案。最好等到树完成构建使用

WidgetsBinding.instance
        .addPostFrameCallback((_){});

样本

WidgetsBinding.instance.addPostFrameCallback((_) {
      if(pageController.hasClients){
              pageController.animateToPage(page index, duration: Duration(milliseconds: 1), curve: Curves.easeInOut);
      }
});

【讨论】:

  • 添加回调函数后页面没有移动索引页面。我已经删除了回调函数并添加了 if(pageController.hasClients){ pageController.animateToPage(page index, duration: Duration(milliseconds: 1), curve: Curves.easeInOut); } 它现在可以工作了。
【解决方案2】:

我用这段代码使appbar的颜色在0位置透明,黑色超过70

backgroundColor: !_scrollController.hasClients
            ? Colors.transparent
            : _scrollController.offset > 70
                ? Color.fromRGBO(7, 7, 7, 1)
                : Colors.transparent,

【讨论】:

    【解决方案3】:

    我已经尝试过上述解决方案,但设置了 ScrollController initialScrollOffset,检查 hasClients 和 jumpTo,WidgetsBinding 没有人为我工作。

    最后通过检查位置'scrollcontroller.positions.length'解决了我的问题

    if (_sc.positions.length == 0 || _sc.position.pixels == 0.0) {
        return Container();
    }
    

    您必须检查控制器位置以消除错误

    参考:https://api.flutter.dev/flutter/widgets/ScrollController/position.html

    【讨论】:

      【解决方案4】:

      初始化滚动控制器:

      ScrollController _scrollController = ScrollController(); 
      

      在你想滚动的地方使用下面的代码:

      SchedulerBinding.instance.addPostFrameCallback((_) {
        _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
      });
      

      【讨论】:

        【解决方案5】:

        我对两个控制器使用相同的 ScrollController 解决了我的问题。 首先我创建 ScrollController():

        ScrollController scollBarController = ScrollController();
        

        在我的代码中:

        Container(
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
            child: Scrollbar(
              controller: scollBarController,
              isAlwaysShown: true,
              child: StaggeredGridView.count(
                controller: scollBarController,
                crossAxisCount: 16,
                staggeredTiles: _staggeredTamanho,
                shrinkWrap: true,
                children: [
                  ...
                ], //listStaggered,
                mainAxisSpacing: 7.0,
              ),
            ),
          ),
        

        【讨论】:

        • 不适合我。滚动条(isAlwaysShown:true,控制器:控制器,子:ListView(控制器:控制器,
        【解决方案6】:

        @carlosx2 的答案是正确的,但如果有人想知道将 WigetsBinding 放在哪里。就是这样。

        @override
        void initState(){
          super.initState();
          WidgetsBinding.instance.addPostFrameCallback((_){
            //write or call your logic
            //code will run when widget rendering complete
          });
        }
        

        【讨论】:

        • 在 Dart 2.12 中实例可以为空。 "方法'addPostFrameCallback'不能被无条件调用,因为接收者可以是'null'。"
        【解决方案7】:

        使用 setState() 方法绑定到与滚动相关的小部件(您的列表视图等)

        setState(() {
            topicsScrollController.animateTo(....);
        });
        

        【讨论】:

          【解决方案8】:

          当您尝试将 ScrollController 绑定到实际上不存在(尚)的小部件时,有时会发生这种情况。所以它尝试绑定,但没有要绑定的 ListView/ScrollView。 假设你有这个代码:

          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Expanded(
                flex: 8,
                child: Container(
                  child: ListView.builder(
                    controller: scrollController,
                    itemCount: messages.length,
                    itemBuilder: (context, index) {
                      return MessageTile(message: messages[index]);
                    }),
                  ),
               ),
           ]),
          

          这里我们动态构建一个 ListView。由于我们之前从未声明过这个 ListView,scrollController 没有任何要绑定的东西。但这很容易解决:

          //首先声明ListView和ScrollController

          final scrollController = ScrollController(initialScrollOffset: 0);
          ListView list = ListView.builder(
            controller: scrollController,
            itemCount: messages.length,
            itemBuilder: (context, index) {
              return MessageTile(message: messages[index]);
            }
          );
          

          // 然后在你的构建函数中只引用已经构建的列表

          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Expanded(
                flex: 8,
                child: Container(
                   child: list,
                ),
              ),
            ]),
          

          【讨论】:

            【解决方案9】:

            我找到了可行的解决方案,但坦率地说,我想该方法不是最佳实践。 在我的情况下, controller.jumpTo() 在附加到任何滚动视图之前被调用。为了解决问题,我延迟了几毫秒,然后调用 .jumpTo(),因为 build 将被调用并且控制器将附加到任何滚动视图。

            Future.delayed(Duration(milliseconds: <some time, ex: 100>), () {
                     _scrollController.jumpTo(50.0);
                    });
            

            我完全同意这是不好的解决方案,但它可以解决问题。

            【讨论】:

              【解决方案10】:

              首先使用其 hasClients 属性检查 scrollController 是否附加到滚动视图。

              if (_scrollController.hasClients) 
                  _scrollController.jumpTo(50.0);
              

              【讨论】:

              • 我的错误是我将控制器连接到 Scrollbar 而不是 SingleChildScrollView child: Scrollbar( child: SingleChildScrollView( controller: _scrollController, 。我想我应该分享一下,以防你们中的任何人有类似的情况。
              • 如何让 listview.builder 始终显示滚动条
              【解决方案11】:

              要设置ScrollController 的初始位置,请使用initialScrollOffset 属性:

              _scrollController = ScrollController(initialScrollOffset: 50.0);
              

              【讨论】:

              • 在新问题中发布您正在使用的确切代码并标记我
              • 下面建议了更好的解决方案。首先检查它是否通过if(_scrollController.hasClients) 附加,然后您应该调用jumpToanimateTo。如果您跳过客户端检查,在 android 上它仍然可以工作.. 但在 IOS 上它会导致问题。
              • 我认为它不会在 IOS(至少在 14 中)和 Flutter 2.5 中引起问题。除非您添加 Scrollbar() 作为父级 - 对我来说,这会导致 IOS 中的异常。
              猜你喜欢
              • 2019-07-30
              • 2019-02-17
              • 1970-01-01
              • 2019-10-30
              • 2020-01-27
              • 2021-06-24
              • 1970-01-01
              • 2019-02-09
              • 2021-08-12
              相关资源
              最近更新 更多