news 2026/10/7 10:14:23

Flutter for OpenHarmony二手物品置换App实战 - 聊天对话实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flutter for OpenHarmony二手物品置换App实战 - 聊天对话实现

聊天功能是买卖双方沟通的核心,买家询问商品细节、协商价格、约定交易方式都在聊天中完成。今天我们来实现"闲置换"的聊天页面,包括消息气泡展示和消息发送功能。

聊天页面的设计思路

聊天页面的核心是消息列表和输入框。消息列表展示双方的对话,自己发的消息靠右显示绿色气泡,对方的消息靠左显示白色气泡。底部是输入框和发送按钮,支持快速发送文字消息。这种左右分布的布局是聊天界面的标准设计,用户一眼就能分清哪些是自己说的。

完整代码实现

import'package:flutter/material.dart';classChatPageextendsStatefulWidget{finalint userId;finalStringuserName;constChatPage({super.key,requiredthis.userId,requiredthis.userName});@overrideState<ChatPage>createState()=>_ChatPageState();}class_ChatPageStateextendsState<ChatPage>{finalTextEditingController_messageController=TextEditingController();finalScrollController_scrollController=ScrollController();finalList<Map<String,dynamic>>_messages=[{'isMe':false,'content':'你好,这个还在吗?','time':'10:30'},{'isMe':true,'content':'在的,有什么问题吗?','time':'10:31'},{'isMe':false,'content':'可以便宜点吗?','time':'10:32'},];

聊天页面接收userId和userName两个参数,用于显示对方的信息和发送消息时标识接收者。定义了两个Controller:_messageController控制输入框,可以获取用户输入的内容和清空输入框;_scrollController控制消息列表滚动,发送新消息后需要自动滚动到底部让用户看到最新消息。_messages是消息列表,每条消息包含是否是自己发的、消息内容、发送时间,实际项目中还需要消息id、发送状态等字段。

@overridevoiddispose(){_messageController.dispose();_scrollController.dispose();super.dispose();}@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:Text(widget.userName),actions:[IconButton(icon:constIcon(Icons.more_vert),onPressed:(){}),],),body:Column(children:[Expanded(child:ListView.builder(controller:_scrollController,padding:constEdgeInsets.all(16),itemCount:_messages.length,itemBuilder:(context,index)=>_buildMessageBubble(_messages[index]),),),_buildInputBar(),],),);}

dispose方法释放两个Controller,这是Flutter开发的好习惯,避免内存泄漏。页面结构用Column垂直排列消息列表和输入框,Expanded让消息列表占据除输入框外的所有空间。AppBar显示对方的用户名,让用户知道是在和谁聊天,右边放更多按钮可以弹出举报、拉黑等选项。消息列表用ListView.builder实现懒加载,传入_scrollController用于控制滚动,padding给列表加内边距让消息不会贴着屏幕边缘。

Widget_buildMessageBubble(Map<String,dynamic>message){finalisMe=message['isMe']asbool;returnPadding(padding:constEdgeInsets.only(bottom:16),child:Row(mainAxisAlignment:isMe?MainAxisAlignment.end:MainAxisAlignment.start,crossAxisAlignment:CrossAxisAlignment.start,children:[if(!isMe)...[CircleAvatar(radius:18,backgroundColor:Colors.grey[300],child:Text(widget.userName[0],style:constTextStyle(fontSize:14)),),constSizedBox(width:8),],

消息气泡的布局根据是否是自己发的来决定对齐方式。自己的消息MainAxisAlignment.end靠右显示,对方的消息MainAxisAlignment.start靠左显示。crossAxisAlignment: CrossAxisAlignment.start让头像和气泡顶部对齐,如果消息很长换行了,头像不会跑到中间去。对方的消息前面显示头像,用CircleAvatar做成圆形,显示用户名的首字母,实际项目中应该显示真实头像图片。展开运算符...[]配合if实现条件渲染,只有对方的消息才显示头像。

Flexible(child:Container(padding:constEdgeInsets.symmetric(horizontal:14,vertical:10),decoration:BoxDecoration(color:isMe?constColor(0xFF07C160):Colors.white,borderRadius:BorderRadius.circular(16),),child:Text(message['content'],style:TextStyle(color:isMe?Colors.white:Colors.black87),),),),if(isMe)...[constSizedBox(width:8),CircleAvatar(radius:18,backgroundColor:constColor(0xFF07C160),child:constText('我',style:TextStyle(fontSize:14,color:Colors.white)),),],],),);}

消息气泡用Flexible包裹,这样长消息会自动换行而不是撑破布局超出屏幕。气泡用圆角矩形,自己的消息是绿色背景白色文字,对方的消息是白色背景黑色文字,这种配色方案和微信类似,用户很熟悉。自己的消息后面显示头像,绿色背景加"我"字,和对方的头像形成对比。padding给气泡内容加内边距,文字不会贴着边缘,阅读更舒适。

Widget_buildInputBar(){returnContainer(padding:constEdgeInsets.symmetric(horizontal:12,vertical:8),decoration:BoxDecoration(color:Colors.white,boxShadow:[BoxShadow(color:Colors.black.withOpacity(0.05),blurRadius:10,offset:constOffset(0,-2),),],),child:SafeArea(child:Row(children:[IconButton(icon:constIcon(Icons.add_circle_outline,color:Colors.grey),onPressed:(){},),

输入栏用Container包裹,加上向上的阴影让它看起来悬浮在消息列表上方,有层次感。SafeArea确保在有底部安全区域的设备上输入框不会被遮挡,比如iPhone的Home Indicator区域。左边放一个加号按钮,点击可以展开更多功能,比如发送图片、位置、商品链接等,这些功能在二手交易场景中很实用,卖家可以发送商品图片,买家可以发送收货地址。

Expanded(child:TextField(controller:_messageController,decoration:InputDecoration(hintText:'输入消息...',hintStyle:TextStyle(color:Colors.grey[400]),filled:true,fillColor:Colors.grey[100],contentPadding:constEdgeInsets.symmetric(horizontal:16,vertical:8),border:OutlineInputBorder(borderRadius:BorderRadius.circular(20),borderSide:BorderSide.none,),),),),constSizedBox(width:8),GestureDetector(onTap:_sendMessage,child:Container(padding:constEdgeInsets.all(10),decoration:constBoxDecoration(color:Color(0xFF07C160),shape:BoxShape.circle,),child:constIcon(Icons.send,color:Colors.white,size:20),),),],),),);}

输入框用Expanded占据中间的空间,圆角胶囊形状,灰色背景,看起来简洁现代。contentPadding控制文字和边框的距离,让输入框看起来不会太挤。发送按钮是一个绿色圆形,里面放发送图标,用GestureDetector处理点击比IconButton更灵活,可以自定义按钮的样式和大小。点击发送按钮调用_sendMessage方法发送消息。

void_sendMessage(){if(_messageController.text.trim().isEmpty)return;setState((){_messages.add({'isMe':true,'content':_messageController.text,'time':'${DateTime.now().hour}:${DateTime.now().minute}',});});_messageController.clear();Future.delayed(constDuration(milliseconds:100),(){_scrollController.animateTo(_scrollController.position.maxScrollExtent,duration:constDuration(milliseconds:300),curve:Curves.easeOut,);});}}

发送消息的方法先检查输入是否为空,trim()去掉首尾空格,避免发送纯空格的无意义消息。然后往消息列表添加新消息,isMe: true表示是自己发的,时间用当前时间。_messageController.clear()清空输入框,方便用户继续输入下一条消息。Future.delayed延迟100毫秒后滚动到底部,这个延迟是为了等待setState完成UI更新,新消息渲染出来后再滚动。animateTo带动画地滚动到maxScrollExtent也就是列表底部,Curves.easeOut让滚动有一个减速的效果,看起来更自然流畅。

聊天功能的扩展

实际项目中聊天功能还需要这些能力:消息类型扩展支持图片、语音、位置、商品卡片等;消息状态显示发送中、已发送、已读等状态;历史消息加载打开聊天页面时加载最近的消息,往上滚动时加载更早的历史消息;实时消息接收用WebSocket保持长连接,对方发消息时实时显示在列表中。

小结

这篇实现了"闲置换"App的聊天页面,包括消息气泡的左右布局、输入框和发送功能。自己的消息绿色靠右,对方的消息白色靠左,发送后自动滚动到底部。这是一个基础的聊天功能,实际项目中还需要扩展更多消息类型和功能。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 19:53:50

python便民医疗服务预约系统 微信小程序vue3

文章目录 便民医疗服务预约系统&#xff08;Python 微信小程序 Vue3&#xff09;核心功能模块技术栈关键实现部署方案扩展方向 --nodejs技术栈--结论源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 便民医疗服务预约系统&#xff08;…

作者头像 李华
网站建设 2026/10/4 22:46:51

基于python的山西文旅网vue3

文章目录Python与Vue3结合开发山西文旅网的技术要点性能优化与部署方案--nodejs技术栈--结论源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;Python与Vue3结合开发山西文旅网的技术要点 后端技术栈&#xff08;Python&#xff09; 使用…

作者头像 李华
网站建设 2026/10/4 20:27:53

基于Springboot+Vue的校园讲座预约系统开题报告

基于SpringbootVue的校园讲座预约系统开题报告 一、课题研究背景与意义&#xff08;一&#xff09;研究背景 在高校学术建设与学风培育的进程中&#xff0c;学术讲座、专题报告、行业前沿分享等各类讲座已成为拓展学生学术视野、衔接理论与实践、提升综合素养的重要载体。当前国…

作者头像 李华
网站建设 2026/10/6 2:11:01

基于SpringBoot + Vue的农产品销售平台

文章目录 前言一、详细操作演示视频二、具体实现截图三、技术栈1.前端-Vue.js2.后端-SpringBoot3.数据库-MySQL4.系统架构-B/S 四、系统测试1.系统测试概述2.系统功能测试3.系统测试结论 五、项目代码参考六、数据库代码参考七、项目论文示例结语 前言 &#x1f49b;博主介绍&a…

作者头像 李华
网站建设 2026/10/6 10:56:01

Java计算机毕设之基于Java的歌唱演出网站订票系统基于SpringBoot的演唱会门票购票网站系统(完整前后端代码+说明文档+LW,调试定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/10/6 4:42:09

【笔记】【周期】

目录 《周期》核心解读笔记 第一类:基本面周期 —— 经济、政府、企业的底层逻辑 1. 经济周期 2. 政府调节周期 3. 企业盈利周期 第二类:心理周期 —— 投资人的情绪钟摆 1. 心理钟摆 2. 风险态度周期 第三类:市场周期 —— 信贷、房地产、股市的具体玩法 1. 信贷…

作者头像 李华