我正在尝试基于friendlychat example创建一个扑朔迷离的聊天应用。使用StreamBuilder(或者在我的情况下实际上是BlocBuilder),使用Firefire快照流中的消息填充ListView。我希望所有的消息都显示在聊天打开时,如图中所示。另外,当新消息从另一个用户或当前用户添加到Firestore集合中时,我希望一次从最底层的一个动画化新消息,而不是一次全部动画。这是我的问题。
所以看来我需要找出来自流的消息列表中的哪些项是新的。我只是通过考虑新列表与旧列表的长度差异来解决这一问题。然后,我尝试使用ListView.builder(请参见代码)中的AnimationController.forward()为基于长度差异的列表中的新项目设置动画。从其他用户收到消息时,此方法有效,但从当前设备/用户发送时则无效。它开始播放动画,但是有一些错误的行为(结束得太快或什么)。必须有更好的方法来实现所需的行为。有什么建议?
body: BlocBuilder<ChatBloc, ChatState>(builder: (context, state) {
if (state is ChatLoaded) {
return Container(
child: BlocBuilder<AuthBloc, AuthState>(
builder: (context, authState) {
final messages = state.messagesLoaded;
if (listOfmsg.length != messages.length) {
diff = messages.length - listOfmsg.length;
listOfmsg = messages;
print(diff);
} else {
diff = 0;
}
final listBuilder = ListView.builder(
padding: new EdgeInsets.all(8),
reverse: true,
itemBuilder: (_, int index) {
final message = messages[index];
if (index <= diff - 1) {
var msg = ChatMessageWithAnimation(
child: ChatMessage(
message: message,
userId: authState is AuthAuthenticated
? authState.userId
: null,
),
animationController: new AnimationController(
vsync: this,
duration: new Duration(milliseconds: 1400)),
);
msg.animationController.forward();
return msg;
}
return ChatMessage(
message: message,
userId: authState is AuthAuthenticated
? authState.userId
: null,
);
},
itemCount: messages.length,
);
return Column(
children: <Widget>[
Flexible(
child: listBuilder,
),
new Divider(height: 1),
new Container(
decoration:
new BoxDecoration(color: Theme.of(context).cardColor),
child: _buildTextComposer(authState is AuthAuthenticated
? authState.userId
: null),
),
],
);
}),
decoration: Theme.of(context).platform == TargetPlatform.iOS
? new BoxDecoration(
border:
Border(top: new BorderSide(color: Colors.grey[200])))
: null,
);
}
return Container();
}));
class ChatMessageWithAnimation extends StatelessWidget {
ChatMessageWithAnimation({this.child, this.text, this.animationController});
final String text;
final AnimationController animationController;
final Widget child;
@override
Widget build(BuildContext context) {
return new SizeTransition(
sizeFactor: new CurvedAnimation(
parent: animationController, curve: Curves.easeOut),
child: this.child);
}
}