|
|
@@ -0,0 +1,210 @@
|
|
|
+import 'package:flutter/material.dart';
|
|
|
+
|
|
|
+import '../model/msg.dart';
|
|
|
+import '../util/ToastUtil.dart';
|
|
|
+
|
|
|
+/// 聊天页面
|
|
|
+class ChatPage extends StatefulWidget {
|
|
|
+ const ChatPage({super.key});
|
|
|
+
|
|
|
+ @override
|
|
|
+ State<StatefulWidget> createState() {
|
|
|
+ return ChatPageState();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class ChatPageState extends State<ChatPage> {
|
|
|
+ /// TextField操作控制器
|
|
|
+ final TextEditingController _editingController = TextEditingController();
|
|
|
+
|
|
|
+ /// ListView的滚动控制器
|
|
|
+ final ScrollController _scrollController = ScrollController();
|
|
|
+
|
|
|
+ /// 输入框焦点
|
|
|
+ final _inputFocusNode = FocusNode();
|
|
|
+
|
|
|
+ /// 消息列表
|
|
|
+ final List<Msg> _msgList = [];
|
|
|
+
|
|
|
+ /// 添加消息到消息列表中
|
|
|
+ void _addMsg2List(String msg, bool isMe) {
|
|
|
+ setState(() {
|
|
|
+ String msgText;
|
|
|
+ if (isMe) {
|
|
|
+ msgText = "我:$msg";
|
|
|
+ } else {
|
|
|
+ msgText = "对方:$msg";
|
|
|
+ }
|
|
|
+ _msgList.add(
|
|
|
+ Msg(isMe: isMe, msg: msgText, createTime: DateTime.now().millisecond),
|
|
|
+ );
|
|
|
+ });
|
|
|
+ Future.delayed(const Duration(milliseconds: 300), () {
|
|
|
+ //延迟300毫秒,再滚动到列表底部
|
|
|
+ _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 发送消息
|
|
|
+ void _sendMsg(String msg) {
|
|
|
+ if (msg.isEmpty) {
|
|
|
+ ToastUtil.showToast("请输入要发送的消息内容");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //添加消息到列表中
|
|
|
+ _addMsg2List(msg, true);
|
|
|
+ // 延迟生成对方的回复消息
|
|
|
+ Future.delayed(const Duration(milliseconds: 150), () {
|
|
|
+ //添加消息到列表中
|
|
|
+ _addMsg2List(replyMessage2Client(msg), false);
|
|
|
+ });
|
|
|
+ //清除输入框的内容
|
|
|
+ _editingController.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 生成回复消息
|
|
|
+ String replyMessage2Client(String clientMsg) {
|
|
|
+ return clientMsg
|
|
|
+ .replaceAll("我", "你")
|
|
|
+ .replaceAll("吗", "")
|
|
|
+ .replaceAll("?", "!")
|
|
|
+ .replaceAll("?", "!");
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 构建聊天气泡
|
|
|
+ Widget _buildMsgBubble(Msg msg) {
|
|
|
+ return Container(
|
|
|
+ padding: const EdgeInsets.all(15.0),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color:
|
|
|
+ msg.isMe
|
|
|
+ ? const Color.fromARGB(255, 164, 208, 238)
|
|
|
+ : const Color.fromARGB(255, 153, 231, 169),
|
|
|
+ borderRadius: BorderRadius.circular(12),
|
|
|
+ ),
|
|
|
+ // 消息文本
|
|
|
+ child: Text(msg.msg),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 构建聊天消息列表项
|
|
|
+ Widget _buildMsgItem(Msg msg) {
|
|
|
+ Widget content;
|
|
|
+ // 自己发的
|
|
|
+ if (msg.isMe) {
|
|
|
+ content = Row(
|
|
|
+ // 如果是自己发的,则在右边
|
|
|
+ mainAxisAlignment: MainAxisAlignment.end,
|
|
|
+ children: [
|
|
|
+ // 聊天气泡
|
|
|
+ _buildMsgBubble(msg),
|
|
|
+ // 头像
|
|
|
+ _buildAvatar(msg),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ // 对方发的
|
|
|
+ content = Row(
|
|
|
+ // 如果是自己发的,则在右边
|
|
|
+ mainAxisAlignment: MainAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ // 头像
|
|
|
+ _buildAvatar(msg),
|
|
|
+ // 聊天气泡
|
|
|
+ _buildMsgBubble(msg),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+ return Container(padding: const EdgeInsets.all(8.0), child: content);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 构建头像
|
|
|
+ Widget _buildAvatar(Msg msg) {
|
|
|
+ return Container(
|
|
|
+ margin: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
|
+ child: CircleAvatar(
|
|
|
+ radius: 20,
|
|
|
+ backgroundColor: Colors.grey,
|
|
|
+ child: Text(
|
|
|
+ msg.isMe ? "我" : "对方",
|
|
|
+ style: const TextStyle(color: Colors.white),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return Scaffold(
|
|
|
+ appBar: AppBar(
|
|
|
+ leading: IconButton(
|
|
|
+ onPressed: () {
|
|
|
+ Navigator.pop(context, null);
|
|
|
+ },
|
|
|
+ icon: const Icon(Icons.arrow_back),
|
|
|
+ ),
|
|
|
+ title: const Text("聊天页"),
|
|
|
+ ),
|
|
|
+ body: Column(
|
|
|
+ children: [
|
|
|
+ Expanded(
|
|
|
+ flex: 1,
|
|
|
+ child: ListView.builder(
|
|
|
+ controller: _scrollController,
|
|
|
+ itemCount: _msgList.length,
|
|
|
+ itemBuilder: (BuildContext context, int index) {
|
|
|
+ return _buildMsgItem(_msgList[index]);
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Center(
|
|
|
+ child: Column(
|
|
|
+ children: [
|
|
|
+ Container(height: 0.3, color: Colors.grey),
|
|
|
+ Padding(
|
|
|
+ padding: const EdgeInsets.symmetric(
|
|
|
+ vertical: 15.0,
|
|
|
+ horizontal: 18.0,
|
|
|
+ ),
|
|
|
+ child: Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Expanded(
|
|
|
+ flex: 1,
|
|
|
+ child: TextField(
|
|
|
+ // 输入框焦点
|
|
|
+ focusNode: _inputFocusNode,
|
|
|
+ // 点击外部区域,关闭软键盘
|
|
|
+ onTapUpOutside: (event) {
|
|
|
+ _inputFocusNode.unfocus();
|
|
|
+ },
|
|
|
+ controller: _editingController,
|
|
|
+ decoration: const InputDecoration(
|
|
|
+ //提示文字
|
|
|
+ hintText: "请输入要发送的消息",
|
|
|
+ //边框
|
|
|
+ border: OutlineInputBorder(),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Container(
|
|
|
+ margin: const EdgeInsets.only(left: 5.0),
|
|
|
+ child: ElevatedButton(
|
|
|
+ child: const Text("发送"),
|
|
|
+ onPressed: () {
|
|
|
+ var msg = _editingController.text;
|
|
|
+ _sendMsg(msg);
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|