Flutter-ListView.builder:初始滚动位置

时间:2019-08-15 01:59:12

标签: listview flutter dart chat native

我想设置ListView.builder的初始滚动位置,我希望列表从底部0.0开始

如果我在listView上设置reverse,我当然会将初始滚动位置设为所需的滚动位置,但是我需要的是让最后一个孩子位于底部,这是一个聊天应用程序。

这是列表生成器,MessageItem()是聊天消息

ListView.builder(
                    shrinkWrap: true,
                    controller: _scrollController,
                    itemCount: snapshot.data.documents.length,
                    padding: EdgeInsets.all(10.0),
                    itemBuilder: (BuildContext context, int index) =>
                        MessageItem(
                            index: index,
                            document: snapshot.data.documents[index],
                            myId: myId));

这是某人send消息

时的动画

_scrollController.animateTo(
                _scrollController.position.maxScrollExtent,
                duration: const Duration(milliseconds: 500),
                curve: Curves.easeOut);

动画工作正常。


我想要的是当用户进入聊天室时列表滚动位置已经在底部。

4 个答案:

答案 0 :(得分:2)

为避免错误(在滚动列表未附加任何列表的情况下),请使用WidgetsBinding在构建就绪后拉出。


void _scrollToBottom() {
    if (_scrollController.hasClients) {
      _scrollController.animateTo(_scrollController.position.maxScrollExtent,
          duration: Duration(milliseconds: 300), curve: Curves.elasticOut);
    } else {
      Timer(Duration(milliseconds: 400), () => _scrollToBottom());
    }
 }

@override
Widget build(BuildContext context) {

  WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom());

  {...} //rest of code;
}

答案 1 :(得分:1)

我感到您很痛苦,因为这是必不可少的要求,因为在一次聊天中可能有成千上万的消息。

要解决此问题,您可以使用

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

构建小部件树后立即触发此回调,因此您只需

scrollController.jump(scrollController.position.maxScrollExtent);

但是,如果您有异步显示消息的功能,那是行不通的,也就是说,在具有某些功能的initstate之后,该功能会将其从firestore文档中拉出。 在这种情况下,您首先需要加载它们,然后再执行上述步骤。希望这会有所帮助。

答案 2 :(得分:0)

您可以设置ScrollController's属性之一:initialScrollOffset

但是在您知道目标项目/索引的偏移位置的情况下。

AboutPage.objects.first()

请注意,此示例假定列表的窗口小部件的大小是恒定大小,但是如果列表中没有恒定的窗口小部件大小,则您必须能够计算的最终偏移位置您的目标商品-这是另外一个问题

或者,如果您希望它始终是最后一项/索引,那么它会容易得多:

ScrollController _controller = ScrollController(initialScrollOffset: itemHeight * index)

答案 3 :(得分:0)

对我来说,解决方案是:

SingleChildScrollView(
                reverse: true,
                child: Container(),
              ),

ListView也具有反向属性。