Firebase Flatter/Firestore:如何将项目添加到滚动流中(在完成抓取时保留滚动位置)?
我有一个聊天室(Firebase Flatter/Firestore:如何将项目添加到滚动流中(在完成抓取时保留滚动位置)?,firebase,listview,flutter,stream,stream-builder,Firebase,Listview,Flutter,Stream,Stream Builder,我有一个聊天室(ListView),里面有我只想根据需要加载的消息 因此,当聊天最初加载时,我希望加载最后n条消息,当用户向上滚动时,我也希望获取较旧的消息 每当新消息到达firebase集合时,都应将其添加到列表视图中。我通过使用StreamBuilder实现了这一点,它获取最后n条消息的流,其中n是一个存储在状态中的变量,我可以增加该状态以加载更多消息(它是获取最后n条消息流的函数的参数) 但在我当前的实现中,问题在于,即使在我向上滚动时获取了更多的消息并将其添加到listview,它也会立
ListView
),里面有我只想根据需要加载的消息
因此,当聊天最初加载时,我希望加载最后n条消息,当用户向上滚动时,我也希望获取较旧的消息
每当新消息到达firebase集合时,都应将其添加到列表视图中。我通过使用StreamBuilder
实现了这一点,它获取最后n条消息的流,其中n是一个存储在状态中的变量,我可以增加该状态以加载更多消息(它是获取最后n条消息流的函数的参数)
但在我当前的实现中,问题在于,即使在我向上滚动时获取了更多的消息并将其添加到listview,它也会立即跳回底部(因为listview被重建,而scrollposition没有保留)。如何防止这种情况发生?此问题与ListView或滚动位置无关。这些是自动保存的。问题必须在代码中的其他地方。查看下面的示例,了解创建列表、添加新项目然后重置列表如何保持滚动位置或移动到正确的位置:
class ListViewStream60521383 extends StatefulWidget {
@override
_ListViewStream60521383State createState() => _ListViewStream60521383State();
}
class _ListViewStream60521383State extends State<ListViewStream60521383> {
List<String> _itemList;
@override
void initState() {
resetItems();
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: ListView.builder(
reverse: true,
itemCount: _itemList.length,
itemBuilder: (context, index){
return Container(
height: 40,
child: Text(_itemList[index]),
);
},
),
),
Row(
children: <Widget>[
RaisedButton(
onPressed: addMoreItems,
child: Text('Add items'),
),
RaisedButton(
onPressed: resetItems,
child: Text('Reset items'),
)
],
)
],
);
}
void addMoreItems(){
int _currentListCount = _itemList.length;
setState(() {
_itemList.addAll(List.generate(60, (index) => 'item ${index + _currentListCount}'));
});
}
void resetItems(){
setState(() {
_itemList = List.generate(60, (index) => 'item $index');
});
}
}
class ListViewStream60521383扩展StatefulWidget{
@凌驾
_ListViewStream60521383State createState()=>\u ListViewStream60521383State();
}
类_ListViewStream60521383State扩展状态{
列表_itemList;
@凌驾
void initState(){
重置项目();
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回列(
儿童:[
扩大(
子项:ListView.builder(
相反:是的,
itemCount:_itemList.length,
itemBuilder:(上下文,索引){
返回容器(
身高:40,
子项:文本(_itemList[index]),
);
},
),
),
划船(
儿童:[
升起的按钮(
onPressed:addMoreItems,
子项:文本(“添加项”),
),
升起的按钮(
按下:重置项目,
子项:文本(“重置项”),
)
],
)
],
);
}
void addMoreItems(){
int\u currentListCount=\u itemList.length;
设置状态(){
_addAll(List.generate(60,(index)=>'item${index+\u currentListCount}');
});
}
作废重置项目(){
设置状态(){
_itemList=List.generate(60,(index)=>“item$index”);
});
}
}
此问题与ListView或滚动位置无关。这些是自动保存的。问题必须在代码中的其他地方。查看下面的示例,了解创建列表、添加新项目然后重置列表如何保持滚动位置或移动到正确的位置:
class ListViewStream60521383 extends StatefulWidget {
@override
_ListViewStream60521383State createState() => _ListViewStream60521383State();
}
class _ListViewStream60521383State extends State<ListViewStream60521383> {
List<String> _itemList;
@override
void initState() {
resetItems();
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: ListView.builder(
reverse: true,
itemCount: _itemList.length,
itemBuilder: (context, index){
return Container(
height: 40,
child: Text(_itemList[index]),
);
},
),
),
Row(
children: <Widget>[
RaisedButton(
onPressed: addMoreItems,
child: Text('Add items'),
),
RaisedButton(
onPressed: resetItems,
child: Text('Reset items'),
)
],
)
],
);
}
void addMoreItems(){
int _currentListCount = _itemList.length;
setState(() {
_itemList.addAll(List.generate(60, (index) => 'item ${index + _currentListCount}'));
});
}
void resetItems(){
setState(() {
_itemList = List.generate(60, (index) => 'item $index');
});
}
}
class ListViewStream60521383扩展StatefulWidget{
@凌驾
_ListViewStream60521383State createState()=>\u ListViewStream60521383State();
}
类_ListViewStream60521383State扩展状态{
列表_itemList;
@凌驾
void initState(){
重置项目();
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回列(
儿童:[
扩大(
子项:ListView.builder(
相反:是的,
itemCount:_itemList.length,
itemBuilder:(上下文,索引){
返回容器(
身高:40,
子项:文本(_itemList[index]),
);
},
),
),
划船(
儿童:[
升起的按钮(
onPressed:addMoreItems,
子项:文本(“添加项”),
),
升起的按钮(
按下:重置项目,
子项:文本(“重置项”),
)
],
)
],
);
}
void addMoreItems(){
int\u currentListCount=\u itemList.length;
设置状态(){
_addAll(List.generate(60,(index)=>'item${index+\u currentListCount}');
});
}
作废重置项目(){
设置状态(){
_itemList=List.generate(60,(index)=>“item$index”);
});
}
}
您应该看一看问题指南:您应该看一看问题指南:此代码仅在按下按钮时才将项目添加到列表中,但当新邮件到达集合时,我希望在Streambuilder的流中包含更多文档。该按钮仅表示与接收相同的效果来自流的新数据。目的是一样的。我向您展示的问题不是ListView中信息的显示,而是代码中的其他地方。我想我明白您的观点。保留scrollposition的问题可能是因为我在无状态小部件中有streambuilder,并且每当重建streambuilder时(因为我更改了获取流的查询)。scrollcontroller已重建,没有最后一个scrollposition。我会尝试一下,如果有用的话,把它贴在这里。非常感谢。事实上,我已经根据你的回答找到了我的问题。我很高兴能帮上忙!此代码仅在按下按钮时将项目添加到列表中,但当新消息到达集合时,我希望在Streambuilder的流中包含更多文档。该按钮仅表示从流接收新数据的效果。目的是一样的。我向您展示的问题不是ListView中信息的显示,而是代码中的其他地方。我想我明白您的观点。保留scrollposition的问题可能是因为我在无状态小部件中有streambuilder,并且每当重建streambuilder时(因为我更改了获取流的查询)。scrollcontroller已重建,但没有