繁体   English   中英

Flutter - 如何滚动到列表视图的底部?

[英]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 行以上,它就很难滚动到裸露的底部。 消息的行数越多,滚动到底部的次数就越少。

这是我进入聊天时的样子:

但如果我进一步向下滚动,这是聊天的底部:

我注意到还有一种情况:

  1. 我进入聊天。
  2. 它像第一张图片一样向下滚动。
  3. 如果我点击屏幕上的任何位置,它会继续滚动到列表视图的底部,就像第二张图片一样。

为什么会发生这种情况,我该如何解决?

我做了什么,使用 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM