Flutter实战一Flutter聊天应用(十八)
在上一篇文章中,我们完成了基本的添加聊天功能,但是还没有在聊天列表显示添加的新聊天,在这篇文章中我们将实现这个功能——在聊天列表中展示所有的聊天。
首先,我们在/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聊天应用(十八)相关推荐
- Flutter实战一Flutter聊天应用(二十)
在上一篇文章<Flutter实战一Flutter聊天应用(十九)>中,我们完成了删除用户的逻辑,就是将会话的有效性设置为false就可以了.那么当会话的有效性为false时,用户再次添加该 ...
- Flutter实战一Flutter聊天应用(十六)
在上一篇文章<Flutter实战一Flutter聊天应用(十五)>中,我们完成了登陆屏幕.在用户登陆成功后,会在本地创建一个LandingInformation文件,以使应用程序在启动时可 ...
- Flutter实战一Flutter聊天应用(十五)
在上一篇文章<Flutter实战一Flutter聊天应用(十四)>中,我们完成了注册屏幕.为了保持应用程序入口只有一个,即登陆屏幕,用户注册完成之后会返回手机号码.密码到登陆屏幕,让用户点 ...
- Flutter实战一Flutter聊天应用(汇总)
纸聊 这个应用程序使用Google的Flutter移动框架开发,是一个实时聊天应用程序,为了能专注于APP设计,应用程序的服务端使用Googler的Firebase平台.程序程序的名称为纸聊,意为像传 ...
- Flutter实战一Flutter聊天应用(五)
我们的应用程序现在已经有了一个好看的UI,但是我们还没有一个后端.所以我们要买一个云服务器,然后再安装数据库?当然不是!我们可以使用Firebase平台作为后端,那么Firebase是什么呢? Fir ...
- Flutter实战一Flutter聊天应用(十九)
在上一篇文章中,我们完成了聊天列表的用户界面与功能代码.在用户添加完会话后,聊天列表会增加对应的会话项,通过点击会话项,可以进入聊天屏幕.在这一篇文章中,我们主要是修改lib/chat_screen. ...
- Flutter实战一Flutter聊天应用(十)
首先,我们要修复一下之前几篇文章中存在的缺陷.在发送超过两行的消息时,屏幕上显示的消息不会自动换行,会超出最大宽度.我们可以通过将Text包装在Container控件中,再添加一个width属性,使其 ...
- Flutter实战一Flutter聊天应用(八)
现在,我们将使用Firebase服务将聊天消息数据存储并同步到公用共享实时数据库上的云.我们需要使用firebase_database插件,用于在Firebase数据库存储和同步消息,还需要使用fir ...
- Flutter实战一Flutter聊天应用(十四)
优化输入体验 在进行下一步之前,我们先优化一下注册的体验: 正在输入注册信息时,点击屏幕空白部分,清除当前文本输入框的焦点,同时收起键盘. 正在输入注册信息时,直接收起键盘,再点击空白部分,清除当前文 ...
最新文章
- linux连接wifi账户密码忘了怎么办,wifi登录密码忘了怎么办?
- 10-Linux 基本指令
- 拒绝某个用户或组应用组策略
- 狼羊菜过河问题深入学习分析——Java语言描述版
- python异常值检测的方法_Python实现非正太分布的异常值检测方式
- 岭回归不仅仅是正则化作用
- linux我ll查不到usr,Linux学习-文件查寻
- 手写spring编程事务
- CSS3的边框(二)
- 线段树和zkw线段树
- Retrofit+Rxjava服务器IP轮询重试机制实现
- NetCore控制台实现自定义CommandLine功能
- uni-app 更改默认组件样式
- windows 下pcl的安装和编译
- Xshell5突然连不上虚拟机
- 微信小程序上传图片失败总结
- Android商品详情页上拉查看详情
- R 回归 虚拟变量na_互助问答第92期:虚拟变量问题
- 机器视觉核心之工业相机
- DBLP数据集用weka数据挖掘 xml转csv格式文件