chat_page.dart 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import 'package:flutter/material.dart';
  2. import '../model/msg.dart';
  3. import '../util/ToastUtil.dart';
  4. /// 聊天页面
  5. class ChatPage extends StatefulWidget {
  6. const ChatPage({super.key});
  7. @override
  8. State<StatefulWidget> createState() {
  9. return ChatPageState();
  10. }
  11. }
  12. class ChatPageState extends State<ChatPage> {
  13. /// TextField操作控制器
  14. final TextEditingController _editingController = TextEditingController();
  15. /// ListView的滚动控制器
  16. final ScrollController _scrollController = ScrollController();
  17. /// 输入框焦点
  18. final _inputFocusNode = FocusNode();
  19. /// 消息列表
  20. final List<Msg> _msgList = [];
  21. /// 添加消息到消息列表中
  22. void _addMsg2List(String msg, bool isMe) {
  23. setState(() {
  24. String msgText;
  25. if (isMe) {
  26. msgText = "我:$msg";
  27. } else {
  28. msgText = "对方:$msg";
  29. }
  30. _msgList.add(
  31. Msg(isMe: isMe, msg: msgText, createTime: DateTime.now().millisecond),
  32. );
  33. });
  34. Future.delayed(const Duration(milliseconds: 300), () {
  35. //延迟300毫秒,再滚动到列表底部
  36. _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
  37. });
  38. }
  39. /// 发送消息
  40. void _sendMsg(String msg) {
  41. if (msg.isEmpty) {
  42. ToastUtil.showToast("请输入要发送的消息内容");
  43. return;
  44. }
  45. //添加消息到列表中
  46. _addMsg2List(msg, true);
  47. // 延迟生成对方的回复消息
  48. Future.delayed(const Duration(milliseconds: 150), () {
  49. //添加消息到列表中
  50. _addMsg2List(replyMessage2Client(msg), false);
  51. });
  52. //清除输入框的内容
  53. _editingController.clear();
  54. }
  55. /// 生成回复消息
  56. String replyMessage2Client(String clientMsg) {
  57. return clientMsg
  58. .replaceAll("我", "你")
  59. .replaceAll("吗", "")
  60. .replaceAll("?", "!")
  61. .replaceAll("?", "!");
  62. }
  63. /// 构建聊天气泡
  64. Widget _buildMsgBubble(Msg msg) {
  65. return Container(
  66. padding: const EdgeInsets.all(15.0),
  67. decoration: BoxDecoration(
  68. color:
  69. msg.isMe
  70. ? const Color.fromARGB(255, 164, 208, 238)
  71. : const Color.fromARGB(255, 153, 231, 169),
  72. borderRadius: BorderRadius.circular(12),
  73. ),
  74. // 消息文本
  75. child: Text(msg.msg),
  76. );
  77. }
  78. /// 构建聊天消息列表项
  79. Widget _buildMsgItem(Msg msg) {
  80. Widget content;
  81. // 自己发的
  82. if (msg.isMe) {
  83. content = Row(
  84. // 如果是自己发的,则在右边
  85. mainAxisAlignment: MainAxisAlignment.end,
  86. children: [
  87. // 聊天气泡
  88. _buildMsgBubble(msg),
  89. // 头像
  90. _buildAvatar(msg),
  91. ],
  92. );
  93. } else {
  94. // 对方发的
  95. content = Row(
  96. // 如果是自己发的,则在右边
  97. mainAxisAlignment: MainAxisAlignment.start,
  98. children: [
  99. // 头像
  100. _buildAvatar(msg),
  101. // 聊天气泡
  102. _buildMsgBubble(msg),
  103. ],
  104. );
  105. }
  106. return Container(padding: const EdgeInsets.all(8.0), child: content);
  107. }
  108. /// 构建头像
  109. Widget _buildAvatar(Msg msg) {
  110. return Container(
  111. margin: const EdgeInsets.symmetric(horizontal: 8.0),
  112. child: CircleAvatar(
  113. radius: 20,
  114. backgroundColor: Colors.grey,
  115. child: Text(
  116. msg.isMe ? "我" : "对方",
  117. style: const TextStyle(color: Colors.white),
  118. ),
  119. ),
  120. );
  121. }
  122. @override
  123. Widget build(BuildContext context) {
  124. return Scaffold(
  125. appBar: AppBar(
  126. leading: IconButton(
  127. onPressed: () {
  128. Navigator.pop(context, null);
  129. },
  130. icon: const Icon(Icons.arrow_back),
  131. ),
  132. title: const Text("聊天页"),
  133. ),
  134. body: Column(
  135. children: [
  136. Expanded(
  137. flex: 1,
  138. child: ListView.builder(
  139. controller: _scrollController,
  140. itemCount: _msgList.length,
  141. itemBuilder: (BuildContext context, int index) {
  142. return _buildMsgItem(_msgList[index]);
  143. },
  144. ),
  145. ),
  146. Center(
  147. child: Column(
  148. children: [
  149. Container(height: 0.3, color: Colors.grey),
  150. Padding(
  151. padding: const EdgeInsets.symmetric(
  152. vertical: 15.0,
  153. horizontal: 18.0,
  154. ),
  155. child: Row(
  156. mainAxisAlignment: MainAxisAlignment.start,
  157. children: [
  158. Expanded(
  159. flex: 1,
  160. child: TextField(
  161. // 输入框焦点
  162. focusNode: _inputFocusNode,
  163. // 点击外部区域,关闭软键盘
  164. onTapUpOutside: (event) {
  165. _inputFocusNode.unfocus();
  166. },
  167. controller: _editingController,
  168. decoration: const InputDecoration(
  169. //提示文字
  170. hintText: "请输入要发送的消息",
  171. //边框
  172. border: OutlineInputBorder(),
  173. ),
  174. ),
  175. ),
  176. Container(
  177. margin: const EdgeInsets.only(left: 5.0),
  178. child: ElevatedButton(
  179. child: const Text("发送"),
  180. onPressed: () {
  181. var msg = _editingController.text;
  182. _sendMsg(msg);
  183. },
  184. ),
  185. ),
  186. ],
  187. ),
  188. ),
  189. ],
  190. ),
  191. ),
  192. ],
  193. ),
  194. );
  195. }
  196. }