我正在使用ListView.builder
进行聊天。
情况如下:用户键入新的聊天消息,这种情况发生时,我将新消息存储在状态中,因此itemCount
增加了一个。
如果我在列表的末尾,我会直接在顶部看到新项目,一切都很好。
但是,如果我在聊天过程中并且添加了一个项目,则视图会滚动一点。如何禁用此行为?我想这有点合理,因为在double
状态下滚动偏移量仍与ScrollControllers
相同,但是如果还有一个项目,看起来就好像在滚动...
有没有很好的方法可以做到这一点?我猜手动方法是测量新项目的高度,然后再次手动设置正确的ScrollController偏移量。
答案 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()));
}
},
);
}
}