在上一篇文章中,我们完成了聊天列表的用户界面与功能代码。在用户添加完会话后,聊天列表会增加对应的会话项,通过点击会话项,可以进入聊天屏幕。在这一篇文章中,我们主要是修改lib/chat_screen.dart的代码,也就是最早的聊天屏幕。

首先打开lib/chat_screen.dart,在ChatScreen中添加五个参数,messages是会话对应的消息列表,myNamesheName是会话双方的名称,myPhoneshePhone则是双方的手机号码,也是唯一标识符。我们需要这些参数来将发送的消息写入到双方的数据节点。

class ChatScreen extends StatefulWidget {ChatScreen({this.messages, this.myName, this.sheName, this.myPhone, this.shePhone});final String messages;final String myName;final String sheName;final String myPhone;final String shePhone;@overrideState createState() => new ChatScreenState(messages);
}

接下来在ChatScreenState中添加两个数据库连接,chatsReference连接会话列表,messagesReference连接具体每一个会话中的信息。还有一个ScaffoldState类型的GlobalKey变量,是用来控制聊天屏幕的脚手架(Scaffold)的状态,比如在底部显示提示信息。

class ChatScreenState extends State<ChatScreen> {ChatScreenState(this._messages);final String _messages;static final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();final TextEditingController _textController = new TextEditingController();final chatsReference = FirebaseDatabase.instance.reference().child('chats');final messagesReference = FirebaseDatabase.instance.reference().child('messages');bool _isComposing = false;//...
}

我们再修改一下ChatScreenState中的_sendMessage方法,会话的一方只要发送了一条消息,就会更新双方的聊天列表中,显示最新的消息内容与消息发送的时间。这里保存的最新时间,是聊天列表排序的依据,这样聊天列表就会以消息的更新时间排序。

class ChatScreenState extends State<ChatScreen> {//...void _sendMessage({String text, String imageUrl}) {String time = new DateTime.now().toString();messagesReference.child(_messages).push().set({'text': text,'imageUrl': imageUrl,'senderName': widget.myName,'timestamp': time});chatsReference.child('${widget.shePhone}/${widget.myPhone}/lastMessage').set(text);chatsReference.child('${widget.shePhone}/${widget.myPhone}/timestamp').set(time);chatsReference.child('${widget.myPhone}/${widget.shePhone}/lastMessage').set(text);chatsReference.child('${widget.myPhone}/${widget.shePhone}/timestamp').set(time);}//...
}

在聊天屏幕的右上方,我们需要增加一个弹出菜单,使用PopupMenuButton控件,在标题栏右方增加一个按钮,点击即可弹出选项菜单,更多关于弹出菜单按钮的内容,可以查看《Flutter进阶—质感设计之弹出菜单》。当用户点击删除选项时,会话双方的activate都将被设置成false,表示这个会话已经无效。

class ChatScreenState extends State<ChatScreen> {//...@overrideWidget build(BuildContext context) {return new Scaffold(key: _scaffoldKey,appBar: new AppBar(title: new Text(widget.sheName),centerTitle: true,elevation: 1.0,actions: <Widget>[new PopupMenuButton<String>(onSelected: (String value) {if (value == "delete") {chatsReference.child('${widget.shePhone}/${widget.myPhone}/activate').set("false");chatsReference.child('${widget.myPhone}/${widget.shePhone}/activate').set("false");_scaffoldKey.currentState.showSnackBar(new SnackBar(content: new Text("删除成功!"),));}},itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[new PopupMenuItem<String>(value: "delete", child: new Text('删除会话')),])]),body: new Stack(children: <Widget>[//...]),);}
}

当会话已经被被设置为无效状态时,应用程序不会自动返回到聊天列表屏幕,因此当用户再次发送消息时,我们应该提示用户该会话已经被删除。修改一下ChatScreenState中的_handleSubmitted方法,在发送消息之前先判断当前会话是否有效,有效时调用_sendMessage方法发送消息,无效则使用脚手架来显示提示信息。

class ChatScreenState extends State<ChatScreen> {//...Future _handleSubmitted(String text) async {chatsReference.child('${widget.myPhone}/${widget.shePhone}/activate').onValue.listen((Event event) {if (event.snapshot.value == "false") {_scaffoldKey.currentState.showSnackBar(new SnackBar(content: new Text("会话已经被删除了哦!"),));} else {if (text.trim() == "") return;_textController.clear();_isComposing = false;_sendMessage(text: text);}});}//...
}

关于聊天屏幕的更多样式修改,可以查看chat_screen.dart文件了解详情。现在我们打开group_chat_list_body.dart文件,修改一下_GroupChatListBodyStatebuild方法,当会话为无效时,不显示该会话。

class _GroupChatListBodyState extends State<GroupChatListBody> {//...@overrideWidget build(BuildContext context) {return new FirebaseAnimatedList(//...itemBuilder: (BuildContext context, DataSnapshot snapshot,Animation<double> animation) {return new SizeTransition(sizeFactor: animation,child: snapshot.value["activate"] == "false"? null: new GroupChatListBodyItem(//...),);},);}
}

Flutter实战一Flutter聊天应用(十九)相关推荐

  1. Flutter实战一Flutter聊天应用(二十)

    在上一篇文章<Flutter实战一Flutter聊天应用(十九)>中,我们完成了删除用户的逻辑,就是将会话的有效性设置为false就可以了.那么当会话的有效性为false时,用户再次添加该 ...

  2. Flutter实战一Flutter聊天应用(十六)

    在上一篇文章<Flutter实战一Flutter聊天应用(十五)>中,我们完成了登陆屏幕.在用户登陆成功后,会在本地创建一个LandingInformation文件,以使应用程序在启动时可 ...

  3. Flutter实战一Flutter聊天应用(十五)

    在上一篇文章<Flutter实战一Flutter聊天应用(十四)>中,我们完成了注册屏幕.为了保持应用程序入口只有一个,即登陆屏幕,用户注册完成之后会返回手机号码.密码到登陆屏幕,让用户点 ...

  4. Flutter实战一Flutter聊天应用(汇总)

    纸聊 这个应用程序使用Google的Flutter移动框架开发,是一个实时聊天应用程序,为了能专注于APP设计,应用程序的服务端使用Googler的Firebase平台.程序程序的名称为纸聊,意为像传 ...

  5. Flutter实战一Flutter聊天应用(五)

    我们的应用程序现在已经有了一个好看的UI,但是我们还没有一个后端.所以我们要买一个云服务器,然后再安装数据库?当然不是!我们可以使用Firebase平台作为后端,那么Firebase是什么呢? Fir ...

  6. Flutter实战一Flutter聊天应用(十八)

    在上一篇文章中,我们完成了基本的添加聊天功能,但是还没有在聊天列表显示添加的新聊天,在这篇文章中我们将实现这个功能--在聊天列表中展示所有的聊天. 首先,我们在/lib目录下新建一个group_cha ...

  7. Flutter实战一Flutter聊天应用(十)

    首先,我们要修复一下之前几篇文章中存在的缺陷.在发送超过两行的消息时,屏幕上显示的消息不会自动换行,会超出最大宽度.我们可以通过将Text包装在Container控件中,再添加一个width属性,使其 ...

  8. Flutter实战一Flutter聊天应用(九)

    在这篇文章中,我们将允许用户在聊天消息中发送图像,从设备检索图像文件,并将文本和图像数据存储在Google云端存储Bucket中.由于我们使用Firebase云储存,应用程序将变得更加健壮和可扩展.它 ...

  9. Flutter实战一Flutter聊天应用(十四)

    优化输入体验 在进行下一步之前,我们先优化一下注册的体验: 正在输入注册信息时,点击屏幕空白部分,清除当前文本输入框的焦点,同时收起键盘. 正在输入注册信息时,直接收起键盘,再点击空白部分,清除当前文 ...

最新文章

  1. TensorRT Samples: GoogleNet
  2. 学界 | 进化算法可以不再需要计算集群,开普敦大学的新方法用一块GPU也能刷新MNIST记录
  3. ubuntu部署java环境
  4. 中国二氧化碳激光器行业现状研究与可行性分析报告2022-2028年版
  5. redis出现过多command 慢查询slowlog出现command命令
  6. php: +1天, +3个月, strtotime(): +1 day, +3 month
  7. python中的map,feilter,和reduce函数
  8. Golang练习题(自己认为比较不错的)
  9. python安装完毕后,用pip安装,提示找不到ssl模块
  10. ElasticSearch7.2只能用localhost访问但不能用IP地址访问---ElasticSearch工作笔记027
  11. 数据工作-百度统计初体验
  12. UVa101 - The Blocks Problem
  13. 二级c语言笔试57,二级C语言笔试真题与答案.doc
  14. python3 爬取搜狗微信的文章
  15. flume中HDFS IO error
  16. instagram获取图片地址和视频地址
  17. 计算机软件工程国家标准汇编目录
  18. 《安富莱嵌入式周报》第210期:2021.04.26--2021.05.02
  19. OSChina 周五乱弹 —— 我想当个昏君
  20. Java小程序,编写一个迷你DVD租借系统(控制台输出)

热门文章

  1. OpenCV:图片的几何变换
  2. Python使用库读取数据
  3. 建设城市(city)(【CCF】NOI Online 能力测试2 入门组第三题 )
  4. [转]linux用户管理
  5. stm32 CRC-16校验代码,单片机ModBUS-CRC16校验
  6. Android studio无法创建类和接口问题解决办法。提示 Unable to parse template Class
  7. 内存读写函数实现进程间通信
  8. Flex的Tree全部展开收缩,ji展开选中单个节点
  9. java.lang.InstantiationException:
  10. java解析xml文件