在顶部添加新项目时,请在L​​istView中保持滚动位置

时间:2018-08-14 15:20:43

标签: flutter

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

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

如果我在列表的末尾,我会直接在顶部看到新项目,一切都很好。

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

有没有很好的方法可以做到这一点?我猜手动方法是测量新项目的高度,然后再次手动设置正确的ScrollController偏移量。

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

这是为列表顶部添加静态/恒定高度(高度: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()));
        }
      },
    );
  }
}