Flutter 在我用颤振设计的聊天应用程序中,有没有办法自动滚动到新消息
我已经厌倦了pub.dev中的示例,并在线查看了帮助信息,但我对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
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
}
}