在顶部添加新项目时在 ListView 中保持滚动位置
Posted
技术标签:
【中文标题】在顶部添加新项目时在 ListView 中保持滚动位置【英文标题】:Keep scroll position in ListView when adding new item on top 【发布时间】:2019-01-21 12:13:47 【问题描述】:我正在使用ListView.builder
进行聊天。
场景如下:用户输入新的聊天消息,当发生这种情况时,我将新消息存储在状态中,因此itemCount
增加了 1。
如果我在列表的末尾,我直接在顶部看到新项目,一切正常。
但是,如果我在聊天过程中添加了一个项目,则视图会滚动一点。如何禁用此行为?我想这有点道理,因为滚动偏移在ScrollControllers
状态下仍然是相同的double
,但是如果还有一个项目,它看起来就像滚动...
有什么好办法吗?我猜手动方法是测量新项目的高度并再次手动设置正确的 ScrollController 偏移量.. 但是我
【问题讨论】:
我认为“手动方法”是正确的方法,因为您正在重建ListView
。
为它提出问题。这应该是原生包含在较低层中的。您不应该手动计算大小
这对动态高度的项目有什么解决方案吗?我有完全相同的问题。
还需要解决方案,有什么消息吗?
【参考方案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 行为的解决方案,而不是建议解决方法。以上是关于在顶部添加新项目时在 ListView 中保持滚动位置的主要内容,如果未能解决你的问题,请参考以下文章
在 Android 中的顶部 ListView 项目上方(以及最后一个项目下方)添加边距
我想在滚动时在列表视图中添加 500 张图像,并删除当前不在屏幕上的项目