I use this code to scroll:

WidgetsBinding.instance?.addPostFrameCallback((_) => _scrollToEnd());

_scrollToEnd() method is:

_scrollController.animateTo(
  _scrollController.position.maxScrollExtent,
  duration: const Duration(
    milliseconds: 200,
  curve: Curves.easeInOut,

想象一下,这是一个普通的聊天屏幕。如果信息只有一行,它就会滚动到最下面。但是一旦信息达到2行以上,它就很难滚动到最底部。信息的行数越多,滚动到底部的次数就越少。

这就是我进入聊天室时的样子。

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

我注意到还有一种情况,那就是。

  • I enter the chat.
  • It scrolls down like on the first image.
  • If i tap anywhere on the screen, it continues to scroll to the bare bottom of the listview like on the second image.
  • 为什么会发生这种情况,我怎样才能解决这个问题?

    2 个评论
    你能不能包括一个列表项,底层小部件用的是什么?
    请看看@Alwayss Bijoy的答案。我认为你问错了问题,他的答案可能是你需要/你想使用的东西:)
    android
    ios
    flutter
    dart
    mobile
    busuu
    busuu
    发布于 2021-10-26
    7 个回答
    Alwayss Bijoy
    Alwayss Bijoy
    发布于 2022-10-20
    0 人赞同

    我所做的是,使用一个listView和反向的true,并在儿童中使用map.reversed的列表,我在下面给你我的代码例子。

    ListView(
              reverse: true,
              children: controller.listMessageData.reversed
               .map((e) => Container(child: Text(e.title));
        
    Kaushik Chandru
    Kaushik Chandru
    发布于 2022-10-20
    0 人赞同

    只是一个变通方法,但它应该能像预期那样工作。在列表视图中使用夹持物理学。在最大范围内添加一个额外的数字

     _scrollController.animateTo(
     _scrollController.position.maxScrollExtent+300,
     duration: const Duration(
       milliseconds: 200,
      curve: Curves.easeInOut,
        
    这是迄今为止最接近的答案。它起作用了,现在它滚动到了最底部。但是我注意到,在ios上没有 "拖动到底部以外 "的效果,因为有夹持物理学。有可能保留这种效果吗?
    你可以把物理学改成Bouncephysics或普通的滚动物理学,但你可能会看到一个额外的反弹到最后,然后它就会在原地折断,这可能看起来有点怪异。
    是的,我注意到现在有一个反弹的效果。有什么办法可以解决这个问题吗?
    试着增加近似值。例如,如果最后一条信息是4条线。添加一个值为120(30x4)。这样你就可以使用你选择的任何物理学,而且不会反弹。
    Faizan Darwesh
    Faizan Darwesh
    发布于 2022-10-20
    0 人赞同

    使用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),
        
    我试了一下,还是同样的问题。
    busuu
    busuu
    发布于 2022-10-20
    0 人赞同

    我终于找到了一个解决方案。没有一个答案对我有用,或部分有用,但我很感谢你试图回答。

    对我来说,我所要做的就是把

    reverse: true
    

    在ListView构建器中,然后每当你返回信息时,你需要以如下方式返回。

    return messages[messages.length - 1 - index];
    

    这是最重要的部分。

    你是个天才。节省了我的时间。谢谢。
    Marius Atasiei
    Marius Atasiei
    发布于 2022-10-20
    0 人赞同

    Use should use the reverse property.

    ListView.builder(
      reverse: true,
      itemCount: 10,
      itemBuilder: (_, index) {
        return ListTile(title: Text(index.toString()));
        
    A. Tratseuski
    A. Tratseuski
    发布于 2022-10-20
    0 人赞同

    当我不得不在项目展开时为其添加滚动时,我也遇到了类似的问题。 我的猜测是,你在向列表中添加新元素时,在相同的构建中调用animate to,所以最大的滚动范围在元素的渲染后发生了变化,你滚动到了前一个元素,或者类似的东西。

    the code goes like this:

      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);
          WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToItem());
    

    并在第一次发射时重置我的状态。

       WidgetsBinding.instance.addPostFrameCallback((_) {
                      i = 0;
                      _scrollToItem();
    

    代码有点乱,但我希望能有帮助。

    Taras Mazepa
    Taras Mazepa
    发布于 2022-10-20
    0 人赞同

    这里有一个解决方案,可以一直向下滚动到最后,而不用手工添加任何额外的像素。唯一的缺点是,你只能使用Curves.linear作为动画。

        Future.doWhile(() {
          if (scrollController.position.extentAfter == 0)
            return Future.value(false);
          return scrollController