【问题标题】:Keep scroll position in ListView when adding new item on top在顶部添加新项目时在 ListView 中保持滚动位置
【发布时间】:2019-01-21 12:13:47
【问题描述】:

我正在使用ListView.builder 进行聊天。

场景如下:用户输入新的聊天消息,当发生这种情况时,我将新消息存储在状态中,因此itemCount 增加了 1。

如果我在列表的末尾,我直接在顶部看到新项目,一切正常。

但是,如果我在聊天过程中添加了一个项目,则视图会滚动一点。如何禁用此行为?我想这有点道理,因为滚动偏移在ScrollControllers 状态下仍然是相同的double,但是如果还有一个项目,它看起来就像滚动...

有什么好办法吗?我猜手动方法是测量新项目的高度并再次手动设置正确的 ScrollController 偏移量.. 但是我

【问题讨论】:

  • 我认为“手动方法”是正确的方法,因为您正在重建ListView
  • 为它提出问题。这应该是原生包含在较低层中的。您不应该手动计算大小
  • 这对动态高度的项目有什么解决方案吗?我有完全相同的问题。
  • 还需要解决方案,有什么消息吗?

标签: flutter


【解决方案1】:

这是在列表顶部添加静态/恒定高度(高度:100)的项目的解决方案。

当我检测到列表长度已更改时,我通过调用 _scrollController.jumpTo(newOffect) 以硬编码项目高度更改偏移位置。

效果很好。当一个新项目被添加到顶部时,列表保持在当前位置,没有可见的跳转。

class FeedWidget extends StatefulWidget {
  FeedWidget({
    Key key,
  }) : super(key: key);

  @override
  State<StatefulWidget> createState() => _FeedWidgetState();
}

class _FeedWidgetState extends State<FeedWidget> {
  var _scrollController = ScrollController();
  var _itemsLength = 0;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<List<FeedItem>>(
      stream: Provider.of<FeedRepository>(context).getAll(),
      builder: (BuildContext context, AsyncSnapshot<List<FeedItem>> items) {
        print('Loaded feed data $items');
        switch (items.connectionState) {
          case ConnectionState.waiting:
            return Center(child: CircularProgressIndicator());
          default:
            final newItemsLength = items.data.length;
            if (_itemsLength != 0 && _itemsLength != newItemsLength) {
              final newItemsCount = newItemsLength - _itemsLength;
              print('New items detected: $newItemsCount');
              final newOffset = _scrollController.offset +
                  100 * newItemsCount; //item height is 100
              print(
                  'Setting new offest ${_scrollController.offset} -> $newOffset');
              _scrollController.jumpTo(newOffset);
            }
            print('Items length new = $newItemsLength old = $_itemsLength}');
            _itemsLength = newItemsLength;
            return Flexible(
                child: ListView(
                    key: PageStorageKey('feed'), //keeps scroll position
                    controller: _scrollController,
                    padding: EdgeInsets.only(top: 8, bottom: 32),
                    children: items.data
                        .map((element) => FeedItemCard(item: element)) //item height is 100
                        .toList()));
        }
      },
    );
  }
}

【讨论】:

    【解决方案2】:

    事实上,您不应该将新的聊天项目添加到列表中。而且您必须缓存它们,然后在列表到达顶部或底部后将缓存注入列表中。我希望这个解决方案对你有用。

    【讨论】:

    • 我们必须提供改变 ListView 行为的解决方案,而不是建议解决方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    • 2020-09-22
    • 2015-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多