gpt4 book ai didi

flutter - 在 StreamBuilder 中使用 AnimatedList

转载 作者:行者123 更新时间:2023-12-04 07:30:58 31 4
gpt4 key购买 nike

我正在用 firebase 构建一个聊天应用程序,我目前正在将每条消息作为文档存储在 firebase 的集合中。我使用 StreamBuilder 来获取最新消息并显示它们。我想在收到和发送新消息时添加动画。我曾尝试使用 Animatedlist,但是,我不知道如何使其与 StreamBuilder 一起使用。据我了解,每次添加新消息时,我都必须调用 insertItem 函数。有没有更聪明的方法来做到这一点?或者这将如何实现?
这是我到目前为止:

class Message {
final String uid;
final String message;
final Timestamp timestamp;

Message({this.uid, this.timestamp, this.message});
}

class MessagesWidget extends StatefulWidget {
final String receiver;
MessagesWidget({@required this.receiver});

@override
_MessagesWidgetState createState() => _MessagesWidgetState();
}

class _MessagesWidgetState extends State<MessagesWidget>{
final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();

Tween<Offset> _offset = Tween(begin: Offset(1,0), end: Offset(0,0));

@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Expanded(
child: StreamBuilder<List<Message>>(
stream: DatabaseService(uid: user.uid).getMessages(widget.receiver),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Loading();
default:
final messages = snapshot.data;
return messages.isEmpty
? SayHi(userID: widget.receiver,)
: AnimatedList(
key: _listKey,
physics: BouncingScrollPhysics(),
reverse: true,
initialItemCount: messages.length,
itemBuilder: (context, index, animation) {
final message = messages[index];
return SlideTransition(
position: animation.drive(_offset),
child: MessageWidget(
message: message,
userID: widget.receiver,
isCurrentUser: message.uid == user.uid,
),
);
},
);
}
}),
),
SizedBox(
height: 10,
),
NewMessage(
receiver: widget.receiver,
)
],
),
);
}
}```

最佳答案

您可以更新小部件的 State对此:

class _MessagesWidgetState extends State<MessagesWidget> {
final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();

Tween<Offset> _offset = Tween(begin: Offset(1, 0), end: Offset(0, 0));

Stream<List<Message>> stream;

List<Message> currentMessageList = [];

User user;

@override
void initState() {
super.initState();

user = Provider.of<User>(context, listen: false);

stream = DatabaseService(uid: user.uid).getMessages(widget.receiver);

stream.listen((newMessages) {
final List<Message> messageList = newMessages;

if (_listKey.currentState != null &&
_listKey.currentState.widget.initialItemCount < messageList.length) {
List<Message> updateList =
messageList.where((e) => !currentMessageList.contains(e)).toList();

for (var update in updateList) {
final int updateIndex = messageList.indexOf(update);
_listKey.currentState.insertItem(updateIndex);
}
}

currentMessageList = messageList;
});
}

@override
Widget build(BuildContext context) {
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Expanded(
child: StreamBuilder<List<Message>>(
stream: stream,
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Loading();
default:
final messages = snapshot.data;
return messages.isEmpty
? SayHi(
userID: widget.receiver,
)
: AnimatedList(
key: _listKey,
physics: BouncingScrollPhysics(),
reverse: true,
initialItemCount: messages.length,
itemBuilder: (context, index, animation) {
final message = messages[index];
return SlideTransition(
position: animation.drive(_offset),
child: MessageWidget(
message: message,
userID: widget.receiver,
isCurrentUser: message.uid == user.uid,
),
);
},
);
}
}),
),
SizedBox(
height: 10,
),
NewMessage(
receiver: widget.receiver,
)
],
),
);
}
}

另外,更新您的 Message类到下面的代码:
// Using the equatable package, remember to add it to your pubspec.yaml file
import 'package:equatable/equatable.dart';

class Message extends Equatable{
final String uid;
final String message;
final Timestamp timestamp;

Message({this.uid, this.timestamp, this.message});

@override
List<Object> get props => [uid, message, timestamp];
}

说明: State上面的代码执行以下操作:
  • 它将当前消息存储在一个列表中 currentMessageList外建方法
  • 它监听流以获取新消息并将新列表与 currentMessageList 中的前一个列表进行比较。 .
  • 它获取列表和循环之间的差异以更新 AnimatedList特定索引处的小部件 updateIndex .
  • Message上面的代码执行以下操作:
  • 它覆盖了 ==运算符和对象 hashcode允许在此行中进行检查:List<Message> updateList = messageList.where((e) => !currentMessageList.contains(e)).toList();按预期工作。 [如果不覆盖这些 getter,检查将失败,因为两个不同的 Message具有相同值的对象将不相等]。
  • 它使用 equatable包装以避免锅炉板。
  • 关于flutter - 在 StreamBuilder 中使用 AnimatedList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67929154/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com