2025跨平台Flutter3+Dart3+Getx仿微信电脑端Exe聊天系统Flutter3-WinChat。
flutter3_winchat:基于最新跨平台框架flutter3.27+dart3.6+getx+bitsdojo_window+media_kit+system_tray搭建桌面客户端仿微信聊天exe实例。整合了聊天功能、联系人、收藏、朋友圈、小视频、我的等模块。
技术栈
- 开发工具:Vscode
- 技术框架:Flutter3.27.1+Dart3.6.0
- 窗口管理:bitsdojo_window: ^0.1.6
- 托盘图标:system_tray: ^2.0.3
- 路由/状态管理:get: ^4.7.2
- 本地存储:get_storage: ^2.1.1
- 图片预览:photo_view: ^0.15.0
- 网址预览:url_launcher: ^6.3.1
- 视频组件:media_kit: ^1.2.0
- 文件选择器:file_picker: ^10.2.0
- 富文本编辑器:fleather: ^1.22.0
项目框架结构
flutter3-winchat电脑端聊天项目已经更新到我的原创作品集。
Flutter3.27+bitsdojo_window仿微信客户端聊天Exe
项目入口配置main.dart
- import 'dart:io';
- import 'package:flutter/material.dart';
- import 'package:bitsdojo_window/bitsdojo_window.dart';
- import 'package:get/get.dart';
- import 'package:get_storage/get_storage.dart';
- import 'package:media_kit/media_kit.dart';
- import 'package:system_tray/system_tray.dart';
- import 'utils/common.dart';
- // 公共布局模板
- import 'layouts/index.dart';
- // 路由管理
- import 'router/index.dart';
- void main() async {
- // 初始化get_storage存储类
- await GetStorage.init();
- // 初始化media_kit视频套件
- WidgetsFlutterBinding.ensureInitialized();
- MediaKit.ensureInitialized();
- initSystemTray();
- runApp(const MyApp());
- // 初始化bitsdojo_window窗口
- doWhenWindowReady(() {
- appWindow.size = const Size(850, 620);
- appWindow.minSize = const Size(700, 500);
- appWindow.alignment = Alignment.center;
- appWindow.title = 'Flutter3-WinChat';
- appWindow.show();
- });
- }
- class MyApp extends StatelessWidget {
- const MyApp({super.key});
- @override
- Widget build(BuildContext context) {
- return GetMaterialApp(
- title: 'FLUTTER3 WINCHAT',
- debugShowCheckedModeBanner: false,
- theme: ThemeData(
- colorScheme: ColorScheme.fromSeed(seedColor: Color(0xFF07C160)),
- useMaterial3: true,
- // 修正windows端字体粗细不一致
- fontFamily: Platform.isWindows ? 'Microsoft YaHei' : null,
- ),
- home: const Layout(),
- // 初始路由
- initialRoute: Common.isLogin() ? '/index' :'/login',
- // 路由页面
- getPages: routes,
- );
- }
- }
- // 创建系统托盘图标
- Future<void> initSystemTray() async {
- String trayIco = 'assets/images/tray.ico';
- SystemTray systemTray = SystemTray();
- // 初始化系统托盘
- await systemTray.initSystemTray(
- title: 'system-tray',
- iconPath: trayIco,
- );
- // 右键菜单
- final Menu menu = Menu();
- await menu.buildFrom([
- MenuItemLabel(label: '打开主界面', onClicked: (menuItem) => appWindow.show()),
- MenuItemLabel(label: '隐藏窗口', onClicked: (menuItem) => appWindow.hide()),
- MenuItemLabel(label: '设置中心', onClicked: (menuItem) => Get.toNamed('/setting')),
- MenuItemLabel(label: '关于', onClicked: (menuItem) => {}),
- MenuItemLabel(label: '退出', onClicked: (menuItem) => appWindow.close()),
- ]);
- await systemTray.setContextMenu(menu);
- // 右键事件
- systemTray.registerSystemTrayEventHandler((eventName) {
- debugPrint('eventName: $eventName');
- if (eventName == kSystemTrayEventClick) {
- Platform.isWindows ? appWindow.show() : systemTray.popUpContextMenu();
- } else if (eventName == kSystemTrayEventRightClick) {
- Platform.isWindows ? systemTray.popUpContextMenu() : appWindow.show();
- }
- });
- }
复制代码 使用 bitsdojo_window 插件进行窗口管理。支持无边框窗口,窗口尺寸大小,自定义系统操作按钮(最大化/最小化/关闭)。
https://pub-web.flutter-io.cn/packages/bitsdojo_window
使用 system_tray 插件管理系统托盘图标。
https://pub-web.flutter-io.cn/packages/system_tray
flutter3公共布局
项目整体布局分为菜单栏+侧边栏+右侧主区域三个模块。
- class Layout extends StatefulWidget {
- const Layout({
- super.key,
- this.activitybar = const Activitybar(),
- this.sidebar,
- this.child,
- this.showSidebar = true,
- });
- final Widget? activitybar; // 左侧菜单栏
- final Widget? sidebar; // 侧边栏
- final Widget? child; // 右侧内容区域
- final bool showSidebar; // 是否显示侧边栏
- @override
- State<Layout> createState() => _LayoutState();
- }
- class _LayoutState extends State<Layout> {
- // 置顶窗口
- bool winTopMost = false;
-
- @override
- void initState() {
- super.initState();
- }
- @override
- void dispose() {
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: Colors.grey[100],
- body: Flex(
- direction: Axis.horizontal,
- children: [
- // 左侧菜单栏
- MoveWindow(
- child: widget.activitybar
- ),
- // 侧边栏
- Visibility(
- visible: widget.showSidebar,
- child: SizedBox(
- // ...
- ),
- ),
- // 主体容器
- Expanded(
- child: Column(
- children: [
- // 导航栏
- WindowTitleBarBox(
- child: Row(
- children: [
- Expanded(
- child: MoveWindow(),
- ),
- // 右上角操作按钮组
- Winbtn(
- // ...
- ),
- ],
- ),
- ),
- // 内容区域
- Expanded(
- child: Container(
- child: widget.child,
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- );
- }
- }
复制代码 flutter3路由配置
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import '../utils/common.dart';
- /* 引入路由页面 */
- import '../views/auth/login.dart';
- import '../views/auth/register.dart';
- // 首页
- import '../views/index/index.dart';
- // 通讯录
- import '../views/contact/index.dart';
- import '../views/contact/addfriends.dart';
- import '../views/contact/newfriends.dart';
- import '../views/contact/uinfo.dart';
- // 收藏
- import '../views/favor/index.dart';
- import '../views/favor/write.dart';
- // 我的
- import '../views/my/index.dart';
- import '../views/my/setting.dart';
- import '../views/my/recharge.dart';
- import '../views/my/wallet.dart';
- // 朋友圈
- import '../views/fzone/index.dart';
- import '../views/fzone/publish.dart';
- // 短视频
- import '../views/fvideo/index.dart';
- // 聊天
- import '../views/chat/group-chat/chat.dart';
- // 路由地址集合
- final Map<String, Widget> routeMap = {
- '/index': const Index(),
- '/contact': const Contact(),
- '/addfriends': const AddFriends(),
- '/newfriends': const NewFriends(),
- '/uinfo': const Uinfo(),
- '/favor': const Favor(),
- '/writefavor': const WriteFavor(),
- '/my': const My(),
- '/setting': const Setting(),
- '/recharge': const Recharge(),
- '/wallet': const Wallet(),
- '/fzone': const Fzone(),
- '/publish': const PublishFzone(),
- '/fvideo': const Fvideo(),
- '/chat': const Chat(),
- };
- final List<GetPage> patchRoute = routeMap.entries.map((e) => GetPage(
- name: e.key, // 路由名称
- page: () => e.value, // 路由页面
- transition: Transition.noTransition, // 跳转路由动画
- middlewares: [AuthMiddleware()], // 路由中间件
- )).toList();
- final List<GetPage> routes = [
- GetPage(name: '/login', page: () => const Login()),
- GetPage(name: '/register', page: () => const Register()),
- ...patchRoute,
- ];
- // 路由拦截
- class AuthMiddleware extends GetMiddleware {
- @override
- RouteSettings? redirect(String? route) {
- return Common.isLogin() ? null : const RouteSettings(name: '/login');
- }
- }
复制代码 flutter3+bitsdojo_window自定义无边框窗口
- Widget build(BuildContext context){
- return Row(
- children: [
- Container(
- child: widget.leading,
- ),
- Visibility(
- visible: widget.minimizable,
- child: MouseRegion(
- cursor: SystemMouseCursors.click,
- child: SizedBox(
- width: 32.0,
- height: 36.0,
- child: MinimizeWindowButton(colors: buttonColors, onPressed: handleMinimize,),
- )
- ),
- ),
- Visibility(
- visible: widget.maximizable,
- child: MouseRegion(
- cursor: SystemMouseCursors.click,
- child: SizedBox(
- width: 32.0,
- height: 36.0,
- child: isMaximized ?
- RestoreWindowButton(colors: buttonColors, onPressed: handleMaxRestore,)
- :
- MaximizeWindowButton(colors: buttonColors, onPressed: handleMaxRestore,),
- ),
- ),
- ),
- Visibility(
- visible: widget.closable,
- child: MouseRegion(
- cursor: SystemMouseCursors.click,
- child: SizedBox(
- width: 32.0,
- height: 36.0,
- child: CloseWindowButton(colors: closeButtonColors, onPressed: handleExit,),
- ),
- ),
- ),
- Container(
- child: widget.trailing,
- ),
- ],
- );
- }
复制代码- // 监听窗口尺寸变化
- @override
- void didChangeMetrics() {
- super.didChangeMetrics();
- WidgetsBinding.instance.addPostFrameCallback((_) {
- setState(() {
- isMaximized = appWindow.isMaximized;
- });
- });
- }
- // 最小化
- void handleMinimize() {
- appWindow.minimize();
- }
- // 设置最大化/恢复
- void handleMaxRestore() {
- appWindow.maximizeOrRestore();
- }
- // 关闭
- void handleExit() {
- showDialog(
- context: context,
- builder: (context) {
- return AlertDialog(
- content: const Text('是否最小化至托盘,不退出程序?', style: TextStyle(fontSize: 16.0),),
- backgroundColor: Colors.white,
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
- elevation: 3.0,
- actionsPadding: const EdgeInsets.all(15.0),
- actions: [
- TextButton(
- onPressed: () {
- Get.back();
- appWindow.hide();
- },
- child: const Text('最小化至托盘', style: TextStyle(color: Colors.blue),)
- ),
- TextButton(
- onPressed: () {
- Get.back();
- appWindow.close();
- },
- child: const Text('退出系统', style: TextStyle(color: Colors.red),)
- ),
- ],
- );
- }
- );
- }
复制代码 flutter3小视频模块
使用media_kit视频套件实现类似抖音短视频,支持点击暂停/播放、上下滑动切换功能。
底部mini播放进度条支持拖拽、点击播放位置功能。- // mini播放进度条
- Positioned(
- bottom: 10.0,
- left: 6.0,
- right: 6.0,
- child: Visibility(
- visible: videoIndex == index && position > Duration.zero,
- child: Listener(
- child: SliderTheme(
- data: SliderThemeData(
- trackHeight: sliderDraging ? 6.0 : 2.0,
- thumbShape: RoundSliderThumbShape(enabledThumbRadius: 4.0), // 调整滑块的大小
- // trackShape: RectangularSliderTrackShape(), // 使用矩形轨道形状
- overlayShape: RoundSliderOverlayShape(overlayRadius: 0), // 去掉Slider默认上下边距间隙
- inactiveTrackColor: Colors.white24, // 设置非活动进度条的颜色
- activeTrackColor: Colors.white, // 设置活动进度条的颜色
- thumbColor: Colors.white, // 设置滑块的颜色
- overlayColor: Colors.transparent, // 设置滑块覆盖层的颜色
- ),
- child: Slider(
- value: sliderValue,
- onChanged: (value) async {
- // debugPrint('当前视频播放时间$value');
- setState(() {
- sliderValue = value;
- });
- // 跳转播放时间
- await player.seek(duration * value.clamp(0.0, 1.0));
- },
- onChangeEnd: (value) async {
- setState(() {
- sliderDraging = false;
- });
- // 继续播放
- if(!player.state.playing) {
- await player.play();
- }
- },
- ),
- ),
- onPointerMove: (e) {
- setState(() {
- sliderDraging = true;
- });
- },
- ),
- ),
- )
复制代码 flutter3聊天模板
聊天编辑框支持多行文本、超过高度出现滚动条、光标位置插入emo表情,支持链接。
优化了类似微信按住说话、左滑取消、右滑转文字功能。
综上就是flutter3实战仿微信客户端聊天系统的一些知识分享,希望对大家有所帮助!
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |