[英]Flutter - how to scroll to the bottom of a listview?
我使用此代码滚动:
WidgetsBinding.instance?.addPostFrameCallback((_) => _scrollToEnd());
_scrollToEnd()
方法是:
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: const Duration(
milliseconds: 200,
),
curve: Curves.easeInOut,
);
想象一下这是一个普通的聊天屏幕。 如果消息在 1 行,它会滚动到底部。 但是,一旦消息到达 2 行以上,它就很难滚动到裸露的底部。 消息的行数越多,滚动到底部的次数就越少。
这是我进入聊天时的样子:
但如果我进一步向下滚动,这是聊天的底部:
我注意到还有一种情况:
为什么会发生这种情况,我该如何解决?
我做了什么,使用 listView 并反转 true,在儿童中使用 map.reversed 列表,我在下面给你我的代码示例。
ListView(
reverse: true,
children: controller.listMessageData.reversed
.map((e) => Container(child: Text(e.title));
使用 ScrollController 因为它运行流畅且易于使用
ScrollController _scrollController = new ScrollController();
像这样将控制器添加到 LisView:
ListView.builder(controller: _scrollController,)
在您的 initState 中导航到此屏幕时滚动到底部
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (_scrollController.hasClients) {
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
curve: Curves.easeOut,
duration: const Duration(milliseconds: 500),
);
}
});
}
只是一种解决方法,但它应该按预期工作。 在列表视图中使用夹紧物理。 添加一个额外的数字到最大范围
_scrollController.animateTo(
_scrollController.position.maxScrollExtent+300,
duration: const Duration(
milliseconds: 200,
),
curve: Curves.easeInOut,
);
使用时应使用 reverse 属性。
ListView.builder(
reverse: true,
itemCount: 10,
itemBuilder: (_, index) {
return ListTile(title: Text(index.toString()));
},
)
当我不得不在展开时向项目添加滚动时,我遇到了类似的问题。 我的猜测是,您在将新元素添加到列表时在同一构建中调用 animate ,因此最大滚动范围在元素渲染后发生变化,并且您滚动到前一个或类似的内容。 我所做的是使用更新的位置值连续几次调用 scrollExtent 。
代码是这样的:
static const int tickCount = 8;
int i = 0;
Future<void> _scrollToEnd() async {
if (mounted && tickCount > i) {
final ScrollPosition position = Scrollable.of(context).position;
final double target = position.pixels +
(position.maxScrollExtent - position.pixels) / (tickCount - i);
position.moveTo(
target,
duration: duration,
curve: Curves.linear,
);
await Future.delayed(duration);
i++;
WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToItem());
}
}
在第一次启动重置时,我声明:
WidgetsBinding.instance.addPostFrameCallback((_) {
i = 0;
_scrollToItem();
});
代码有点乱,但我希望它有帮助
我终于找到了解决方案。 没有一个答案对我有用,或者部分有用,但我感谢您尝试回答。
对我来说,我所要做的就是把
reverse: true
在 ListView 构建器中,然后每当您返回消息时,您需要将其返回为:
return messages[messages.length - 1 - index];
这是最重要的部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.