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

119 篇文章 9 订阅
82 篇文章 1416 订阅

上一篇文章中,我们完成了聊天列表的用户界面与功能代码。在用户添加完会话后,聊天列表会增加对应的会话项,通过点击会话项,可以进入聊天屏幕。在这一篇文章中,我们主要是修改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;

  @override
  State 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> {
  //...
  @override
  Widget 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> {
  //...
  @override
  Widget 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(
                  //...
                ),
        );
      },
    );
  }
}

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何小有

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值