ScrollController 未附加到任何滚动视图
Posted
技术标签:
【中文标题】ScrollController 未附加到任何滚动视图【英文标题】:ScrollController not attached to any scroll views 【发布时间】: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
方法并且滚动视图附加到树后附加。
【参考方案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)
附加,然后您应该调用jumpTo
或animateTo
。如果您跳过客户端检查,在 android 上它仍然可以工作.. 但在 ios 上它会导致问题。
我认为它不会在 IOS(至少在 14 中)和 Flutter 2.5 中引起问题。除非您添加 Scrollbar() 作为父级 - 对我来说,这会导致 IOS 中的异常。以上是关于ScrollController 未附加到任何滚动视图的主要内容,如果未能解决你的问题,请参考以下文章
25.Flutter的ListView监听滚动事件之ScrollController
滚动带有ScrollController的CustomScrollView时,SliverAppbar仍然可见