加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-14 14:56:46 所属栏目:百科 来源:网络整理
导读:在上一篇文章中,我们完成了基本的添加聊天功能,但是还没有在聊天列表显示添加的新聊天,在这篇文章中我们将实现这个功能——在聊天列表中展示所有的聊天。 首先,我们在 /lib 目录下新建一个 group_chat_list_body.dart 文件。在 group_chat_list_body.dar

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

首先,我们在/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;
  @override
  Widget 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.myPphone,this.shePphone});
  final String name;
  final String lastMessage;
  final String timestamp;
  final String messages;
  final String myName;
  final String myPphone;
  final String shePphone;

  @override
  Widget 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;

  @override
  void 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> {
  //...
  @override
  Widget 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文件的代码。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读