2025原创研发flutter3+dart3实战仿微信App聊天系统Flutter3Chat。
flutter3_wechat:基于最新跨平台框架flutter3.32+dart3.8+get_storage+photo_view从0-1打造仿微信app聊天项目。包含聊天、通讯录、我的及朋友圈等模块。实现发送文字+emo表情消息、长按仿微信语音操作、图片/链接预览等功能。
技术栈
- 编辑器:VScode
- 框架技术:Flutter3.32+Dart3.8
- 组件库:material-design3
- 弹窗组件:showDialog/SimpleDialog/showModalBottomSheet/AlertDialog
- 图片预览:photo_view^0.15.0
- 存储组件:get_storage^2.1.1
- 下拉刷新:easy_refresh^3.4.0
- toast提示:toast^0.3.0
- 网址预览组件:url_launcher^6.3.1
项目框架目录
flutter3-chat聊天app项目已经更新到我的原创作品集。
flutter3.32+dart3.8仿微信App聊天界面|朋友圈
flutter3沉浸式渐变导航条
通过配置AppBar提供的可伸缩灵活区域属性 flexibleSpace 搭配gradient即可快速实现渐变导航栏。- AppBar(
- title: Text('Flutter3-Chat'),
- flexibleSpace: Container(
- decoration: const BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.topLeft,
- end: Alignment.bottomRight,
- colors: [
- Color(0xFF0091EA), Color(0xFF07C160)
- ],
- )
- ),
- )
- ),
复制代码 flutter3仿微信PopupMenu下拉菜单/下拉刷新
flutter提供的PopupMenuButton组件实现下拉菜单功能。- PopupMenuButton(
- icon: FStyle.iconfont(0xe62d, size: 17.0),
- offset: const Offset(0, 50.0),
- tooltip: '',
- color: const Color(0xFF353535),
- itemBuilder: (BuildContext context) {
- return <PopupMenuItem>[
- popupMenuItem(0xe666, '发起群聊', 0),
- popupMenuItem(0xe75c, '添加朋友', 1),
- popupMenuItem(0xe603, '扫一扫', 2),
- popupMenuItem(0xe6ab, '收付款', 3),
- ];
- },
- onSelected: (value) {
- switch(value) {
- case 0:
- print('发起群聊');
- break;
- case 1:
- Navigator.pushNamed(context, '/addfriends');
- break;
- case 2:
- print('扫一扫');
- break;
- case 3:
- print('收付款');
- break;
- }
- },
- )
复制代码
下拉刷新、上拉加载更多是通过 easy_refresh 组件实现功能。- EasyRefresh(
- // 下拉加载提示
- header: const ClassicHeader(
- // showMessage: false,
- ),
- // 加载更多提示
- footer: ClassicFooter(),
- // 下拉刷新逻辑
- onRefresh: () async {
- // ...下拉逻辑
- await Future.delayed(const Duration(seconds: 2));
- },
- // 上拉加载逻辑
- onLoad: () async {
- // ...
- },
- child: ListView.builder(
- itemCount: chatList.length,
- itemBuilder: (context, index) {
- return Ink(
- // ...
- );
- },
- ),
- )
复制代码
弹窗功能均是自定义AlertDialog实现效果。通过无限制容器UnconstrainedBox配合SizedBox组件实现自定义窗口大小。- // 关于弹窗
- void aboutAlertDialog(BuildContext context) {
- showDialog(
- context: context,
- builder: (context) {
- return UnconstrainedBox(
- constrainedAxis: Axis.vertical,
- child: SizedBox(
- width: 320.0,
- child: AlertDialog(
- contentPadding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
- backgroundColor: Colors.white,
- surfaceTintColor: Colors.white,
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
- content: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 10.0),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Image.asset('assets/images/logo.png', width: 90.0, height: 90.0, fit: BoxFit.cover,),
- const SizedBox(height: 10.0),
- const Text('Flutter3-WChat', style: TextStyle(color: Color(0xFF0091EA), fontSize: 22.0),),
- const SizedBox(height: 5.0),
- const Text('基于flutter3+dart3开发跨平台仿微信App聊天实例。', style: TextStyle(color: Colors.black45),),
- const SizedBox(height: 20.0),
- Text('©2024/01 Andy Q: 282310962', style: TextStyle(color: Colors.grey[400], fontSize: 12.0),),
- ],
- ),
- ),
- ),
- ),
- );
- }
- );
- }
- // 二维码名片弹窗
- void qrcodeAlertDialog(BuildContext context) {
- showDialog(
- context: context,
- builder: (context) {
- return UnconstrainedBox(
- constrainedAxis: Axis.vertical,
- child: SizedBox(
- width: 320.0,
- child: AlertDialog(
- contentPadding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
- backgroundColor: const Color(0xFF07C160),
- surfaceTintColor: const Color(0xFF07C160),
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(3.0)),
- content: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 10.0),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Image.asset('assets/images/qrcode.png', width: 250.0, fit: BoxFit.cover,),
- const SizedBox(height: 15.0),
- const Text('扫一扫,加我公众号', style: TextStyle(color: Colors.white60, fontSize: 14.0,),),
- ],
- ),
- ),
- ),
- ),
- );
- }
- );
- }
- // 退出登录弹窗
- void logoutAlertDialog(BuildContext context) {
- showDialog(
- context: context,
- builder: (context) {
- return AlertDialog(
- content: const Text('确定要退出登录吗?', style: TextStyle(fontSize: 16.0),),
- backgroundColor: Colors.white,
- surfaceTintColor: Colors.white,
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
- elevation: 2.0,
- actionsPadding: const EdgeInsets.all(15.0),
- actions: [
- TextButton(
- onPressed: () {Navigator.of(context).pop();},
- child: const Text('取消', style: TextStyle(color: Colors.black54),)
- ),
- TextButton(
- onPressed: handleLogout,
- child: const Text('退出登录', style: TextStyle(color: Colors.red),)
- ),
- ],
- );
- }
- );
- }
复制代码 flutter3实现微信朋友圈
- ImageGroup(images: item['images'])
- ImageGroup(
- images: uploadList,
- album: true,
- onChoose: () async {
- Toast.show('选择手机相册图片', duration: 2, gravity: 1);
- },
- )
复制代码
- /// 微信朋友圈九宫格图片
- library;
- import 'package:flutter/material.dart';
- import '../router/fade_route.dart';
- import 'image_viewer.dart';
- import '../utils/index.dart';
- class ImageGroup extends StatelessWidget {
- const ImageGroup({
- super.key,
- this.images,
- this.width = 200.0,
- this.album = false,
- this.limit = 9,
- this.onChoose,
- });
- final List<String>? images; // 图片组
- final double width; // 图片宽度
- final bool album; // 是否相册/专辑(最后面显示+可选择图片)
- final int limit; // 限制多少张
- final Function? onChoose; // 选择图片回调
- int? get count => images?.length;
- List<String>? get imgList => count! >= limit ? images?.sublist(0, limit) : images;
- // 创建可点击预览图片
- createImage(BuildContext context, String img, int key) {
- return GestureDetector(
- child: Hero(
- tag: 'image_${key}_$img', // 放大缩小动画效果标识
- child: img == '+' ?
- Container(color: Colors.transparent, child: const Icon(Icons.add, size: 30.0, color: Colors.black45),)
- :
- Utils.isUrl(img) ?
- Image.network(
- img,
- width: width,
- fit: BoxFit.contain,
- )
- :
- Image.asset(
- img,
- width: width,
- fit: BoxFit.contain,
- ),
- ),
- onTap: () {
- // 选择图片
- if(img == '+') {
- onChoose!();
- }else {
- Navigator.of(context).push(FadeRoute(route: ImageViewer(
- images: album ? imgList!.sublist(0, imgList!.length - 1) : imgList,
- index: key,
- heroTags: imgList!.asMap().entries.map((e) => 'image_${e.key}_${e.value}').toList(),
- )));
- }
- },
- );
- }
- @override
- Widget build(BuildContext context){
- // 一张图片
- if(count == 1 && !album) {
- return SizedBox(
- width: width,
- child: createImage(context, imgList![0], 0),
- );
- }
- if(album && count! < limit) {
- imgList?.add('+');
- }
-
- // 多张图片
- return GridView(
- shrinkWrap: true,
- physics: const NeverScrollableScrollPhysics(),
- gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
- // 横轴元素个数
- crossAxisCount: 3,
- // 纵轴间距
- mainAxisSpacing: 5.0,
- // 横轴间距
- crossAxisSpacing: 5.0,
- // 子组件宽高比例
- childAspectRatio: 1,
- ),
- children: imgList!.asMap().entries.map((e) {
- return Container(
- color: Colors.grey[100],
- child: createImage(context, e.value, e.key),
- );
- }).toList(),
- );
- }
- }
复制代码 flutter3聊天功能
文本框TextField设置maxLines: null即可实现多行文本输入,支持图文emoj混排,网址连接识别等功能。- // 输入框
- Offstage(
- offstage: voiceBtnEnable,
- child: ConstrainedBox(
- constraints: BoxConstraints(maxHeight: 300.0),
- child: TextField(
- decoration: InputDecoration(
- isDense: true,
- hoverColor: Colors.transparent,
- border: OutlineInputBorder(borderSide: BorderSide.none),
- contentPadding: EdgeInsets.fromLTRB(10, 0, 10, 0)
- ),
- style: const TextStyle(fontSize: 16.0,),
- maxLines: null,
- controller: editorController,
- focusNode: editorFocusNode,
- cursorColor: const Color(0xFF07C160),
- onChanged: (value) {},
- ),
- ),
- )
复制代码
- // 语音
- Offstage(
- offstage: !voiceBtnEnable,
- child: GestureDetector(
- child: Container(
- decoration: BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.circular(5),
- ),
- alignment: Alignment.center,
- height: 40.0,
- width: double.infinity,
- child: Text(voiceTypeMap[voiceType], style: const TextStyle(fontSize: 15.0),),
- ),
- onPanStart: (details) {
- setState(() {
- voiceType = 1;
- voicePanelEnable = true;
- });
- },
- onPanUpdate: (details) {
- Offset pos = details.globalPosition;
- double swipeY = MediaQuery.of(context).size.height - 120;
- double swipeX = MediaQuery.of(context).size.width / 2 + 50;
- setState(() {
- if(pos.dy >= swipeY) {
- voiceType = 1; // 松开发送
- }else if (pos.dy < swipeY && pos.dx < swipeX) {
- voiceType = 2; // 左滑松开取消
- }else if (pos.dy < swipeY && pos.dx >= swipeX) {
- voiceType = 3; // 右滑语音转文字
- }
- });
- },
- onPanEnd: (details) {
- // print('停止录音');
- setState(() {
- switch(voiceType) {
- case 1:
- Toast.show('发送录音文件', duration: 1, gravity: 1);
- voicePanelEnable = false;
- break;
- case 2:
- Toast.show('取消发送', duration: 1, gravity: 1);
- voicePanelEnable = false;
- break;
- case 3:
- Toast.show('语音转文字', duration: 1, gravity: 1);
- voicePanelEnable = true;
- voiceToTransfer = true;
- break;
- }
- voiceType = 0;
- });
- },
- ),
- )
复制代码 flutter3绘制聊天箭头
- // 绘制聊天箭头
- class ArrowShape extends CustomPainter {
- ArrowShape({
- required this.arrowColor,
- this.arrowSize = 7,
- });
- final Color arrowColor; // 箭头颜色
- final double arrowSize; // 箭头大小
- @override
- void paint(Canvas canvas, Size size) {
- var paint = Paint()..color = arrowColor;
- var path = Path();
- path.lineTo(-arrowSize, 0);
- path.lineTo(0, arrowSize);
- path.lineTo(arrowSize, 0);
- canvas.drawPath(path, paint);
- }
- @override
- bool shouldRepaint(CustomPainter oldDelegate) {
- return false;
- }
- }
复制代码 综上就是Flutter3+Dart3实战仿微信App聊天项目的一些知识分享,感谢大家的阅读与支持!
附上几个最新项目实例
最新版uniapp+vue3+uv-ui跨三端短视频+直播+聊天【H5+小程序+App端】
Uniapp-DeepSeek跨三端AI助手|uniapp+vue3+deepseek-v3流式ai聊天模板
Electron35-DeepSeek桌面端AI系统|vue3.5+electron+arco客户端ai模板
vue3-webseek网页版AI问答|Vite6+DeepSeek+Arco流式ai聊天打字效果
flutter3-dymall仿抖音直播商城|Flutter3.27短视频+直播+聊天App实例
tauri2.0-admin桌面端后台系统|Tauri2+Vite5+ElementPlus管理后台EXE程序
Tauri2.0+Vite5聊天室|vue3+tauri2+element-plus仿微信|tauri聊天应用
Electron32-ViteOS桌面版os系统|vue3+electron+arco客户端OS管理模板
uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天语音/朋友圈
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |