Flutter 在我用颤振设计的聊天应用程序中,有没有办法自动滚动到新消息

Flutter 在我用颤振设计的聊天应用程序中,有没有办法自动滚动到新消息,flutter,Flutter,我已经厌倦了pub.dev中的示例,并在线查看了帮助信息,但我对flutter开发还不熟悉,所以我不知道它是否因为我没有走上正确的轨道,或者因为我必须对其进行定制以适合我的特定代码而不起作用 这是我的密码 import 'dart:async'; import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:chat_app_tutorial/helper/constants.dart'; import 'packa

我已经厌倦了pub.dev中的示例,并在线查看了帮助信息,但我对flutter开发还不熟悉,所以我不知道它是否因为我没有走上正确的轨道,或者因为我必须对其进行定制以适合我的特定代码而不起作用

这是我的密码

import 'dart:async';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:chat_app_tutorial/helper/constants.dart';
import 'package:chat_app_tutorial/services/database.dart';
import 'package:chat_app_tutorial/widgets/widget.dart';
import 'package:flutter/material.dart';

class ConversationScreen extends StatefulWidget {
  final String chatRoomId;
  ConversationScreen(this.chatRoomId);

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

class _ConversationScreenState extends State<ConversationScreen> {

  DatabaseMethods databaseMethods = new DatabaseMethods();
  TextEditingController messagesController =new TextEditingController();
  ScrollController _controller = new ScrollController();

  Stream ChatMessageStream;



  Widget ChatMessageList(){
    final scrollDirection = Axis.vertical;
    return StreamBuilder(
      stream: ChatMessageStream,
      builder: (context, snapshot){
        return snapshot.hasData ? ListView.builder(
            scrollDirection: scrollDirection,
            controller: _controller,
            children: ChatMessageStream.map<Widget>((data) {
              final index = data[0];
              final height = data[1];
              return AutoScrollTag(
                key: ValueKey(index),
                controller: _controller,
                index: index,
                child: Text('index: $index, height: $height'),
                highlightColor: Colors.black.withOpacity(0.1),
              );
            }).toList(),
            itemCount: snapshot.data.docs.length,
            itemBuilder: (context, index){
              return MessageTile(snapshot.data.docs[index].data()["message"], snapshot.data.docs[index].data()["sentBy"] == Constants.myName);
            }
        ) : Container();
      },
    );
  }

  sendMessage(){
    if(messagesController.text.isNotEmpty){
      Map<String, dynamic> messageMap = {
        "message" : messagesController.text,
        "sentBy" : Constants.myName,
        "time" : DateTime.now().millisecondsSinceEpoch
      };
      databaseMethods.saveConversationMessages(widget.chatRoomId, messageMap);
      messagesController.text = "";

      Timer(Duration(milliseconds: 500),
              () => _controller.jumpTo(_controller.position.maxScrollExtent));
    }

  }

  @override
  void initState() {
    databaseMethods.getConversationMessages(widget.chatRoomId).then((value){
      setState(() {
        ChatMessageStream = value;
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: appBarMain(context),
      body: Container(
        child: Stack(
          children: [
            ChatMessageList(),
            Container(
              alignment: Alignment.bottomCenter,
              child: Container(
                color: Color(0x54ffffff),
                padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
                child: Row(
                  children: [
                    Expanded(
                      child: TextField(
                        controller: messagesController,
                        style: TextStyle(
                            color: Colors.white
                        ),
                        decoration: InputDecoration(
                            hintText: "Type here",
                            hintStyle: TextStyle(
                                color: Colors.white54
                            ),
                            border: InputBorder.none
                        ),
                      ),
                    ),
                    GestureDetector(
                      onTap: (){
                        sendMessage();
                        Timer(
                            Duration(milliseconds: 300),
                                () => _controller
                                .jumpTo(_controller.position.maxScrollExtent));
                      },
                      child: Container(
                          height: 40,
                          width: 40,
                          decoration: BoxDecoration(
                              gradient: LinearGradient(
                                  colors: [
                                    const Color(0x36ffffff),
                                    const Color(0x0fffffff)
                                  ]
                              ),
                              borderRadius: BorderRadius.circular(40)
                          ),
                          padding: EdgeInsets.all(12),
                          child: Image.asset("assets/images/send.png")
                      ),
                    )
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class MessageTile extends StatelessWidget {
  final String message;
  final bool isSentByMe;
  MessageTile(this.message, this.isSentByMe);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(left: isSentByMe?0:24, right: isSentByMe?24:0),
      margin: EdgeInsets.symmetric(vertical: 8),
      width: MediaQuery.of(context).size.width,
      alignment: isSentByMe ? Alignment.centerRight : Alignment.centerLeft,
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8),
        decoration: BoxDecoration(
          gradient: LinearGradient(
            colors: isSentByMe ? [
              const Color(0xff007EF4),
              const Color(0xff2A75BC)
            ]
                : [
              const Color(0x1AFFFFFF),
              const Color(0x1AFFFFFF)
            ],
          ),
          borderRadius: isSentByMe ? BorderRadius.only(
            topLeft: Radius.circular(23),
            topRight: Radius.circular(23),
            bottomLeft: Radius.circular(23)
        )  :
        BorderRadius.only(
            topLeft: Radius.circular(23),
            topRight: Radius.circular(23),
            bottomRight: Radius.circular(23)
    ),
        ),
        child: Text(message, style: TextStyle(
            color: Colors.white,
            fontSize: 17
        ),),
      ),
    );
  }
}



导入'dart:async';
导入“package:scroll_to_index/scroll_to_index.dart”;
导入“package:chat_app_tutorial/helper/constants.dart”;
导入“包:chat_app_tutorial/services/database.dart”;
导入“package:chat_app_tutorial/widgets/widget.dart”;
进口“包装:颤振/材料.省道”;
类ConversationScreen扩展StatefulWidget{
最终字符串聊天室ID;
对话屏幕(此为聊天室ID);
@凌驾
_ConversationScreenState createState()=>_ConversationScreenState();
}
类_ConversationScreenState扩展状态{
DatabaseMethods DatabaseMethods=新的DatabaseMethods();
TextEditingController消息控制器=新建TextEditingController();
ScrollController _controller=新的ScrollController();
流聊天信息流;
Widget ChatMessageList(){
最终滚动方向=轴垂直;
返回流生成器(
stream:ChatMessageStream,
生成器:(上下文,快照){
返回snapshot.hasData?ListView.builder(
滚动方向:滚动方向,
控制器:_控制器,
子项:ChatMessageStream.map((数据){
最终指数=数据[0];
最终高度=数据[1];
返回AutoScrollTag(
键:ValueKey(索引),
控制器:_控制器,
索引:索引,,
子项:文本('index:$index,height:$height'),
highlightColor:颜色。黑色。不透明度(0.1),
);
}).toList(),
itemCount:snapshot.data.docs.length,
itemBuilder:(上下文,索引){
返回MessageTile(snapshot.data.docs[index].data()[“message”],snapshot.data.docs[index].data()[“sentBy”]==Constants.myName);
}
):容器();
},
);
}
sendMessage(){
if(messagesController.text.isNotEmpty){
映射消息映射={
“message”:messagesController.text,
“sentBy”:Constants.myName,
“时间”:DateTime.now().millissecondssinceepoch
};
databaseMethods.saveConversationMessages(widget.chatRoomId,messageMap);
messagesController.text=“”;
计时器(持续时间(毫秒:500),
()=>_controller.jumpTo(_controller.position.maxScrollExtent));
}
}
@凌驾
void initState(){
databaseMethods.getConversationMessages(widget.chatRoomId).then((值){
设置状态(){
ChatMessageStream=值;
});
});
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBarMain(上下文),
主体:容器(
子:堆栈(
儿童:[
ChatMessageList(),
容器(
对齐:对齐.bottomCenter,
子:容器(
颜色:颜色(0x54ffffff),
填充:边缘组。对称(水平:24,垂直:16),
孩子:排(
儿童:[
扩大(
孩子:TextField(
控制器:messagesController,
样式:TextStyle(
颜色:颜色。白色
),
装饰:输入装饰(
hintText:“在此处键入”,
hintStyle:TextStyle(
颜色:Colors.white54
),
边框:InputBorder.none
),
),
),
手势检测器(
onTap:(){
sendMessage();
计时器(
持续时间(毫秒:300),
()=>\u控制器
.jumpTo(_controller.position.maxScrollExtent));
},
子:容器(
身高:40,
宽度:40,
装饰:盒子装饰(
梯度:线性梯度(
颜色:[
常量颜色(0x36ffffff),
常量颜色(0x0fffffff)
]
),
边界半径:边界半径。圆形(40)
),
填充:边缘设置。全部(12),
子级:Image.asset(“assets/images/send.png”)
),
)
],
),
),
),
],
),
),
);
}
}
类MessageTile扩展了无状态小部件{
最终字符串消息;
最终目标是我;
MessageTile(this.message,this.isSentByMe);
@凌驾
小部件构建(构建上下文){
返回容器(
填充:仅限边集(左:isSentByMe?0:24,右:isSentByMe?24:0),
边缘:边缘组。对称(垂直:8),
宽度:MediaQuery.of(context).size.width,
对齐:isSentByMe?对齐。中间右侧:对齐。中间左侧,
子:容器(
填充:边缘组。对称(水平:24,垂直:8),
装饰:盒子装饰(
梯度:线性梯度(
颜色:是我吗[
常量颜色(0xff007EF4),
常量颜色(0xff2A75BC)
]
: [
常量颜色(0x1afffff),
常量颜色(0x1AFFFFFF)
],
_controller.animateTo(_controller.position.maxScrollExtent,
        duration: Duration(milliseconds: 500), curve: Curves.ease);
SchedulerBinding.instance.addPostFrameCallback((_) {
});
children: ChatMessageStream.map<Widget>((data) {
   if (previousLength != data.length)
   {
      _controller.animateTo(_controller.position.maxScrollExtent,
            duration: Duration(milliseconds: 500), curve: Curves.ease);

      previousLength = data.length
   }
}