Анимировать новые элементы последовательно снизу в Listview.builder - PullRequest
0 голосов
/ 18 марта 2020

Я пытаюсь создать приложение чата с флаттером на примере friendlychat . ListView заполняется сообщениями, поступающими из потока моментальных снимков пожарного хранилища с использованием StreamBuilder (или фактически BlocBuilder в моем случае). Я хочу, чтобы все сообщения отображались при открытии чата, как на картинке. Кроме того, когда новые сообщения добавляются в коллекцию firestore, либо от другого пользователя, либо от текущего пользователя, я хочу анимировать новые сообщения из нижнего по очереди, а не все сразу, а затем анимировать. Это моя проблема.

Так что, похоже, мне нужно выяснить, какие элементы в списке сообщений, поступающих из потока, являются новыми. Я справился с этим, просто взяв разницу в длине нового списка по сравнению со старым. Затем я попытался анимировать новые элементы в списке на основе разницы в длине, используя AnimationController.forward () внутри ListView.builder (см. Код). Когда сообщение приходит от другого пользователя, это работает, но не при отправке с текущего устройства / пользователя. Он запускает анимацию, но есть некоторые ошибки (слишком быстрое завершение или что-то в этом роде). Должен быть лучший способ добиться желаемого поведения. Какие-либо предложения?

enter image description here

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);
  }
}
...