Я пытаюсь создать приложение чата с флаттером на примере friendlychat . ListView заполняется сообщениями, поступающими из потока моментальных снимков пожарного хранилища с использованием StreamBuilder (или фактически BlocBuilder в моем случае). Я хочу, чтобы все сообщения отображались при открытии чата, как на картинке. Кроме того, когда новые сообщения добавляются в коллекцию firestore, либо от другого пользователя, либо от текущего пользователя, я хочу анимировать новые сообщения из нижнего по очереди, а не все сразу, а затем анимировать. Это моя проблема.
Так что, похоже, мне нужно выяснить, какие элементы в списке сообщений, поступающих из потока, являются новыми. Я справился с этим, просто взяв разницу в длине нового списка по сравнению со старым. Затем я попытался анимировать новые элементы в списке на основе разницы в длине, используя AnimationController.forward () внутри ListView.builder (см. Код). Когда сообщение приходит от другого пользователя, это работает, но не при отправке с текущего устройства / пользователя. Он запускает анимацию, но есть некоторые ошибки (слишком быстрое завершение или что-то в этом роде). Должен быть лучший способ добиться желаемого поведения. Какие-либо предложения?
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);
}
}