在上一篇文章中,我们完成了基本的添加聊天功能,但是还没有在聊天列表显示添加的新聊天,在这篇文章中我们将实现这个功能——在聊天列表中展示所有的聊天。

首先,我们在/lib目录下新建一个group_chat_list_body.dart文件。在group_chat_list_body.dart中编写一个有状态控件GroupChatListBody,传递两个参数,phone(手机号码)和myName(姓名),手机号码将用于在Firebase实时数据库中访问“/chats/$phone”,以读取当前用户的聊天列表。

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'chat_screen.dart';
import 'prompt_wait.dart';class GroupChatListBody extends StatefulWidget {GroupChatListBody({this.phone,this.myName,Key key,}): super(key: key);final String phone;final String myName;@override_GroupChatListBodyState createState() => new _GroupChatListBodyState(phone);
}class _GroupChatListBodyState extends State<GroupChatListBody> {_GroupChatListBodyState(this._phone);final String _phone;@overrideWidget build(BuildContext context) {return new Text("聊天列表");}
}

回到group_chat_list.dart文件中,在_GroupChatListState中修改一下build方法,使用我们在前面自定义的有状态控件GroupChatListBody。如果参数phone为空,说明还没有读取到用户的手机号码,则暂时显示空白,直到参数phone不为空才显示GroupChatListBody控件。

class _GroupChatListState extends State<GroupChatList> {//...Widget build(BuildContext context) {//...return new Scaffold(appBar: new AppBar(title: new Text("纸聊"),centerTitle: true,elevation: 0.0,),drawer: drawer,body: new Center(child: phone == "null"? null: new GroupChatListBody(phone: phone, myName: name),),//...);}
}

再回到group_chat_list_body.dart文件中,我们新创建一个GroupChatListBodyItem类,这是一个无状态控件,用于展示具体的一个聊天。这个控件所需要的参数有点多,name(对方的名称)、lastMessage(最新的消息)、timestamp(时间戳)、messages(“/messages/$messages”)、myName(名称)、myPphone(手机号码)和shePphone(对方的手机号码)。

GroupChatListBodyItem的顶层是一个GestureDetector控件,其onTap属性是一个匿名方法,内容是导航到一个新屏幕,而新屏幕的内容是ChatScreen控件。ChatScreen控件是应用程序的第一个屏幕,我们只需要修改一下里面的内容就可以直接调用,具体的修改会在下一篇文章中讲解,或者可以在GitHub上直接查看。

class GroupChatListBodyItem extends StatelessWidget {GroupChatListBodyItem({this.name,this.lastMessage,this.timestamp,this.messages,this.myName,this.myPphone,this.shePphone});final String name;final String lastMessage;final String timestamp;final String messages;final String myName;final String myPphone;final String shePphone;@overrideWidget build(BuildContext context) {return new GestureDetector(onTap: () {Navigator.of(context).push(new MaterialPageRoute<Null>(builder: (BuildContext context) {return new ChatScreen(messages: messages,myName: myName,sheName: name,myPphone: myPphone,shePphone: shePphone);},));},child: new Container(decoration: new BoxDecoration(),padding: new EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0),child: new Row(children: <Widget>[new CircleAvatar(child: new Text(name[0]),backgroundColor: Theme.of(context).buttonColor),new Flexible(child: new Column(crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[new Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[new Text("  " + name, textScaleFactor: 1.2),new Text(ReadableTime(timestamp),textAlign: TextAlign.right,style: new TextStyle(color: Theme.of(context).hintColor)),]),new Container(padding: new EdgeInsets.only(top: 2.0),child: new Text("  " + lastMessage,overflow: TextOverflow.ellipsis,style: new TextStyle(color: Theme.of(context).hintColor))),],))],)));}
}

前面的GroupChatListBodyItem中有一个timestamp参数,在Firebase实时数据库是以“2017-08-14 17:16:11.65”的时间戳格式保存的,并非直观的可读格式,因此我们需要进行格式转换。在prompt_wait.dart文件中写一个通用方法ReadableTime,将给定的时间戳转换成直观的可读形式,在prompt_wait.dart中添加以下代码。

String ReadableTime(String timestamp) {List<String> timeList = timestamp.split(" ");List<String> times = timeList[1].split(":");String time;if (new DateTime.now().toString().split(" ")[0] == timeList[0]) {if (int.parse(times[0]) < 6) {time = "凌晨${times[0]}:${times[1]}";} else if (int.parse(times[0]) < 12) {time = "上午${times[0]}:${times[1]}";} else if (int.parse(times[0]) == 12) {time = "中午${times[0]}:${times[1]}";} else {time ="下午${(int.parse(times[0])- 12).toString().padLeft(2,'0')}:${times[1]}";}} else {time = timeList[0];}return time;
}

_GroupChatListBodyState中覆盖initState方法,使控件在初始化时访问Firebase实时数据库中的“chats/$_phone”。将setPersistenceEnabled设置为true,开启数据库的持久性设置,同时调用keepSynced(true),使数据将自动下载并保持同步。

class _GroupChatListBodyState extends State<GroupChatListBody> {//...DatabaseReference _chatsReference;@overridevoid initState() {super.initState();_chatsReference = FirebaseDatabase.instance.reference().child('chats/$_phone');FirebaseDatabase.instance.setPersistenceEnabled(true);_chatsReference.keepSynced(true);}//...
}

最后修改_GroupChatListBodyState中的build方法,使用FirebaseAnimatedList控件读取Firebase实时数据库。参数query设置查询位置,sort设置排序,这里设置成按时间戳排序,defaultChild设置读取时的等待动画。itemBuilder会遍历一次查询到的数据,将这些数据分别创建一个GroupChatListBodyItem控件。

class _GroupChatListBodyState extends State<GroupChatListBody> {//...@overrideWidget build(BuildContext context) {return new FirebaseAnimatedList(query: _chatsReference,sort: (DataSnapshot a, DataSnapshot b) =>b.value["timestamp"].compareTo(a.value["timestamp"]),defaultChild: new CircularProgressIndicator(),itemBuilder: (BuildContext context, DataSnapshot snapshot,Animation<double> animation) {return new SizeTransition(sizeFactor: animation,child: new GroupChatListBodyItem(name: snapshot.value["name"],lastMessage: snapshot.value["lastMessage"],timestamp: snapshot.value["timestamp"],messages: snapshot.value["messages"],myName: widget.myName,myPphone: _phone,shePphone: snapshot.value["phone"],),);},);}
}

大家可以在GitHub上直接查看group_chat_list_body.dart文件、group_chat_list.dart文件和chat_screen.dart文件的代码。

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/chat_screen. ...

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

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

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

    现在,我们将使用Firebase服务将聊天消息数据存储并同步到公用共享实时数据库上的云.我们需要使用firebase_database插件,用于在Firebase数据库存储和同步消息,还需要使用fir ...

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

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

最新文章

  1. linux连接wifi账户密码忘了怎么办,wifi登录密码忘了怎么办?
  2. 10-Linux 基本指令
  3. 拒绝某个用户或组应用组策略
  4. 狼羊菜过河问题深入学习分析——Java语言描述版
  5. python异常值检测的方法_Python实现非正太分布的异常值检测方式
  6. 岭回归不仅仅是正则化作用
  7. linux我ll查不到usr,Linux学习-文件查寻
  8. 手写spring编程事务
  9. CSS3的边框(二)
  10. 线段树和zkw线段树
  11. Retrofit+Rxjava服务器IP轮询重试机制实现
  12. NetCore控制台实现自定义CommandLine功能
  13. uni-app 更改默认组件样式
  14. windows 下pcl的安装和编译
  15. Xshell5突然连不上虚拟机
  16. 微信小程序上传图片失败总结
  17. Android商品详情页上拉查看详情
  18. R 回归 虚拟变量na_互助问答第92期:虚拟变量问题
  19. 机器视觉核心之工业相机
  20. DBLP数据集用weka数据挖掘 xml转csv格式文件

热门文章

  1. 计算机算法设计与分析 递归实现快速排序和随机化实现快速排序
  2. OpenCV:使用python-cv2实现Harr+Adaboost人脸识别
  3. Pycharm(windows)设置中文菜单
  4. python argparse 简明教程
  5. 机器学习笔记网盘分享
  6. Git Bash基本命令,Git提交代码到GitHub,GitHub获取代码到本地
  7. ConcurrentHashMap 底层原理,你真的理解了吗?
  8. Linux防火墙配置与管理(16)
  9. EBS MOAC深入研究(转)
  10. python learning1.py