基于flutter3.x+window_manager+getx桌面端仿macOS系统

2024-04-13 11:04

本文主要是介绍基于flutter3.x+window_manager+getx桌面端仿macOS系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

flutter3_macui桌面端仿macOS系统实战项目完结啦!

原创研发flutter3.19+dart3.3+window_manager+getx等技术构建桌面版macOS系统。支持自定义毛玻璃虚化背景、Dock菜单多级嵌套+自由拖拽排序、可拖拽弹窗等功能。

在这里插入图片描述
支持macOS和windows11两种风格。

在这里插入图片描述

使用技术

  • 编辑器:VScode
  • 框架技术:Flutter3.19.2+Dart3.3.0
  • 窗口管理:window_manager^0.3.8
  • 路由/状态管理:get^4.6.6
  • 本地存储:get_storage^2.1.1
  • 拖拽排序:reorderables^0.6.0
  • 图表组件:fl_chart^0.67.0
  • 托盘插件:system_tray^2.0.3

在这里插入图片描述
在这里插入图片描述

特性

  1. 桌面菜单支持二级弹窗菜单
  2. 整体界面虚化毛玻璃模糊效果
  3. 经典Dock菜单
  4. 程序坞Dock菜单可拖拽式排序、支持二级弹窗式菜单
  5. 丰富视觉效果,自定义桌面主题换肤背景
  6. 可视化多窗口路由,支持弹窗方式打开新路由页面

在这里插入图片描述

项目结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

flutter-os布局模板

在这里插入图片描述

如上图:整体布局分为顶部导航条+桌面菜单+底部Dock菜单三部分。

return Scaffold(key: scaffoldKey,body: Container(// 背景图主题decoration: skinTheme(),// DragToResizeArea缩放窗口child: DragToResizeArea(child: Flex(direction: Axis.vertical,crossAxisAlignment: CrossAxisAlignment.start,children: [// 导航栏WindowTitlebar(onDrawer: () {// 自定义打开右侧drawerscaffoldKey.currentState?.openEndDrawer();},),// 桌面区域Expanded(child: GestureDetector(child: Container(color: Colors.transparent,child: Row(crossAxisAlignment: CrossAxisAlignment.start,children: [Expanded(child: GestureDetector(child: const WindowDesktop(),onSecondaryTapDown: (TapDownDetails details) {posDX = details.globalPosition.dx;posDY = details.globalPosition.dy;},onSecondaryTap: () {debugPrint('桌面图标右键');showDeskIconContextmenu();},),),],),),onSecondaryTapDown: (TapDownDetails details) {posDX = details.globalPosition.dx;posDY = details.globalPosition.dy;},onSecondaryTap: () {debugPrint('桌面右键');showDeskContextmenu();},),),// Dock菜单settingController.settingData['dock'] == 'windows' ?const WindowTabbar():const WindowDock(),],),),),endDrawer: Drawer(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)),width: 300,child: const Settings(),),
);

在这里插入图片描述
在这里插入图片描述

底部Dock菜单滤镜模糊效果,支持macos和windows11两种风格。

在这里插入图片描述

MouseRegion(cursor: SystemMouseCursors.click,onEnter: (event) {setState(() {hoveredIndex = index;});controller.forward(from: 0.0);},onExit: (event) {setState(() {hoveredIndex = -1;});controller.stop();},child: GestureDetector(onTapDown: (TapDownDetails details) {anchorDx = details.globalPosition.dx;},onTap: () {if(item!['children'] != null) {showDockDialog(item!['children']);}},// 缩放动画child: ScaleTransition(alignment: Alignment.bottomCenter,scale: hoveredIndex == index ? controller.drive(Tween(begin: 1.0, end: 1.5).chain(CurveTween(curve: Curves.easeOutCubic))):Tween(begin: 1.0, end: 1.0).animate(controller),child: UnconstrainedBox(child: Stack(alignment: AlignmentDirectional.topCenter,children: [// tooltip提示Visibility(visible: hoveredIndex == index && !draggable,child: Positioned(top: 0,child: SizedOverflowBox(size: Size.zero,child: Container(alignment: Alignment.center,padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 1.0),margin: const EdgeInsets.only(bottom: 20.0),decoration: BoxDecoration(color: Colors.black54,borderRadius: BorderRadius.circular(3.0),),child: Text('${item!['tooltip']}', style: const TextStyle(color: Colors.white, fontSize: 8.0, fontFamily: 'arial')),),),),),// 图片/图标item!['children'] != null ?thumbDock(item!['children']):SizedBox(height: 35.0,width: 35.0,child: item!['type'] != null && item!['type'] == 'icon' ? IconTheme(data: const IconThemeData(color: Colors.white, size: 32.0),child: item!['imgico'],):Image.asset('${item!['imgico']}'),),// 圆点Visibility(visible: item!['active'] != null,child: Positioned(bottom: 0,child: SizedOverflowBox(size: Size.zero,child: Container(margin: const EdgeInsets.only(top: 2.0),height: 4.0,width: 4.0,decoration: BoxDecoration(color: Colors.black87,borderRadius: BorderRadius.circular(10.0),),),),),),],),),),),
)
List dockList = [{'tooltip': 'Flutter3.19', 'imgico': 'assets/images/logo.png'},{'tooltip': 'Safari', 'imgico': 'assets/images/mac/safari.png', 'active': true},{'tooltip': 'Launchpad','imgico': 'assets/images/mac/launchpad.png','children': [{'tooltip': 'Podcasts', 'imgico': 'assets/images/mac/podcasts.png'},{'tooltip': 'Quicktime', 'imgico': 'assets/images/mac/quicktime.png'},{'tooltip': 'Notes', 'imgico': 'assets/images/mac/notes.png'},{'tooltip': 'Reminder', 'imgico': 'assets/images/mac/reminders.png'},{'tooltip': 'Calc', 'imgico': 'assets/images/mac/calculator.png'},]},{'tooltip': 'Appstore', 'imgico': 'assets/images/mac/appstore.png',},{'tooltip': 'Messages', 'imgico': 'assets/images/mac/messages.png', 'active': true},{'type': 'divider'},...{'tooltip': 'Recycle Bin', 'imgico': 'assets/images/mac/bin.png'},
];

在这里插入图片描述
Dock二级菜单采用showDialogPositioned组件实现定位弹窗。

void showDockDialog(data) {anchorDockOffset();showDialog(context: context,barrierColor: Colors.transparent,builder: (context) {return Stack(children: [Positioned(top: anchorDy - 210,left: anchorDx - 120,width: 240.0,height: 210,child: ClipRRect(borderRadius: BorderRadius.circular(16.0),child: BackdropFilter(filter: ImageFilter.blur(sigmaX: 20.0, sigmaY: 20.0),child: Container(padding: const EdgeInsets.symmetric(vertical: 10.0),decoration: const BoxDecoration(backgroundBlendMode: BlendMode.overlay,color: Colors.white,),child: ListView(children: [Container(padding: const EdgeInsets.symmetric(horizontal: 10.0,),child: Wrap(runSpacing: 5.0,spacing: 5.0,children: List.generate(data.length, (index) {final item = data[index];return MouseRegion(cursor: SystemMouseCursors.click,child: GestureDetector(child:  Column(children: [// 图片/图标SizedBox(height: 40.0,width: 40.0,child: item!['type'] != null && item!['type'] == 'icon' ? IconTheme(data: const IconThemeData(color: Colors.black87, size: 35.0),child: item!['imgico'],):Image.asset('${item!['imgico']}'),),SizedBox(width: 70,child: Text(item['tooltip'], style: const TextStyle(color: Colors.black87, fontSize: 12.0), maxLines: 2, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center,),)],),onTap: () {// ...},),);}),),),],),),),),),],);},);
}

flutter3实现桌面菜单

在这里插入图片描述
在这里插入图片描述
桌面菜单使用垂向排列展示。


Widget build(BuildContext context) {return Container(padding: const EdgeInsets.all(10.0),child: Wrap(direction: Axis.vertical,spacing: 5.0,runSpacing: 5.0,children: List.generate(deskList.length, (index) {final item = deskList[index];return MouseRegion(cursor: SystemMouseCursors.click,onEnter: (event) {setState(() {hoveredIndex = index;});},onExit: (event) {setState(() {hoveredIndex = -1;});},child: GestureDetector(onTapDown: (TapDownDetails details) {anchorDx = details.globalPosition.dx;anchorDy = details.globalPosition.dy;},onTap: () {if(item!['children'] != null) {showDeskDialog(item!['children']);}else {showRouteDialog(item);}},child: Container(...),),);}),),);
}

点击桌面图标,采用自定义弹窗组件显示页面内容。

/**桌面弹窗式路由页面  Q:282310962
*/
void showRouteDialog(item) async {// 链接if(item!['link'] != null) {await launchUrl(Uri.parse(item!['link']));return;}// 弹窗图标Widget dialogIcon() {if(item!['type'] != null && item!['type'] == 'icon') {return IconTheme(data: const IconThemeData(size: 16.0),child: item!['imgico'],);}else {return Image.asset('${item!['imgico']}', height: 16.0, width: 16.0, fit: BoxFit.cover);}}// Fdialog参数dynamic dialog = item!['dialog'] ?? {};navigator?.push(FdialogRoute(child: Fdialog(// 标题title: dialog!['title'] ?? Row(children: [dialogIcon(),const SizedBox(width: 5.0,),Text('${item!['title']}',),],),// 内容content: dialog!['content'] ?? ListView(padding: const EdgeInsets.all(10.0),children: [item!['component'] ?? const Center(child: Column(children: [Icon(Icons.layers,), Text('Empty~'),],)),],),titlePadding: dialog!['titlePadding'], // 标题内间距backgroundColor: dialog!['backgroundColor'] ?? Colors.white.withOpacity(.85), // 弹窗背景色barrierColor: dialog!['barrierColor'], // 弹窗遮罩层颜色offset: dialog!['offset'], // 弹窗位置(坐标点)width: dialog!['width'] ?? 800, // 宽度height: dialog!['height'] ?? 500, // 高度radius: dialog!['radius'], // 圆角fullscreen: dialog!['fullscreen'] ?? false, // 是否全屏maximizable: dialog!['maximizable'] ?? true, // 是否显示最大化按钮closable: dialog!['closable'] ?? true, // 是否显示关闭按钮customClose: dialog!['customClose'], // 自定义关闭按钮closeIcon: dialog!['closeIcon'], // 自定义关闭图标actionColor: dialog!['actionColor'], // 右上角按钮组颜色actionSize: dialog!['actionSize'], // 右上角按钮组大小draggable: dialog!['draggable'] ?? true, // 是否可拖拽destroyOnExit: dialog!['destroyOnExit'] ?? false, // 鼠标滑出弹窗是否销毁关闭),));
}

桌面菜单json配置列表。

List deskList = [{'title': 'Flutter3.19', 'imgico': 'assets/images/logo.png', 'link': 'https://flutter.dev/'},{'title': '首页', 'imgico': const Icon(Icons.home_outlined), 'type': 'icon','component': const Home(),'dialog': {'fullscreen': true}},{'title': '工作台', 'imgico': const Icon(Icons.poll_outlined), 'type': 'icon','component': const Dashboard(),},{'title': '组件','imgico': const Icon(Icons.apps),'type': 'icon','children': [{'title': 'Mail', 'imgico': 'assets/images/mac/mail.png'},{'title': 'Info', 'imgico': 'assets/images/mac/info.png'},{'title': 'Editor', 'imgico': 'assets/images/mac/scripteditor.png'},{'title': '下载', 'imgico': const Icon(Icons.download_outlined), 'type': 'icon'},{'title': 'Bug统计', 'imgico': const Icon(Icons.bug_report_outlined), 'type': 'icon'},{'title': '计算器', 'imgico': const Icon(Icons.calculate), 'type': 'icon'},{'title': '图表', 'imgico': const Icon(Icons.bar_chart), 'type': 'icon'},{'title': '打印', 'imgico': const Icon(Icons.print), 'type': 'icon'},{'title': '站内信', 'imgico': const Icon(Icons.campaign), 'type': 'icon'},{'title': '云存储', 'imgico': const Icon(Icons.cloud_outlined), 'type': 'icon'},{'title': '裁剪', 'imgico': const Icon(Icons.crop_outlined), 'type': 'icon'},]},{'title': '私密空间', 'imgico': const Icon(Icons.camera_outlined), 'type': 'icon','component': const Uzone(),},...{'title': '公众号', 'imgico': const Icon(Icons.qr_code), 'type': 'icon','dialog': {'title': const Text('QRcode', style: TextStyle(color: Colors.white60, fontSize: 14.0, fontFamily: 'arial')),'content': Padding(padding: const EdgeInsets.all(10.0),child: Column(mainAxisSize: MainAxisSize.min,children: [Image.asset('assets/images/qrcode_white.png', height: 120.0, fit: BoxFit.contain,),const Spacer(),const Text('扫一扫,关注公众号', style: TextStyle(color: Colors.white60, fontSize: 12.0,),),],),),'backgroundColor': const Color(0xff07c160),'actionColor': Colors.white54,'width': 300,'height': 220,'maximizable': false,'closable': true,'draggable': true,}},
];

在这里插入图片描述
自定义Fdialog弹窗支持如下参数配置

// 标题
final Widget? title;
// 弹窗内容
final Widget content;
// 标题内间距
final EdgeInsetsGeometry? titlePadding;
// 弹窗背景色
final Color? backgroundColor;
// 弹窗遮罩层颜色
final Color? barrierColor;
// 弹窗位置(坐标点)
final Offset? offset;
// 宽度
final num width;
// 高度
final num height;
// 圆角
final double? radius;
// 是否全屏
final bool fullscreen;
// 是否显示最大化按钮
final bool maximizable;
// 是否显示关闭按钮
final bool closable;
// 自定义关闭按钮
final Widget? customClose;
// 自定义关闭图标
final IconData? closeIcon;
// 右上角按钮组颜色
final Color? actionColor;
// 右上角按钮组大小
final double? actionSize;
// 是否可拖拽
final bool draggable;
// 鼠标滑出弹窗是否销毁关闭
final bool destroyOnExit;

Okay,以上就是flutter3+getx开发桌面端os系统的一些分享知识。

https://blog.csdn.net/yanxinyun1990/article/details/136410049

https://blog.csdn.net/yanxinyun1990/article/details/135329724

在这里插入图片描述

这篇关于基于flutter3.x+window_manager+getx桌面端仿macOS系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/899955

相关文章

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

macOS无效Launchpad图标轻松删除的4 种实用方法

《macOS无效Launchpad图标轻松删除的4种实用方法》mac中不在appstore上下载的应用经常在删除后它的图标还残留在launchpad中,并且长按图标也不会出现删除符号,下面解决这个问... 在 MACOS 上,Launchpad(也就是「启动台」)是一个便捷的 App 启动工具。但有时候,应

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置

如何使用Python实现一个简单的window任务管理器

《如何使用Python实现一个简单的window任务管理器》这篇文章主要为大家详细介绍了如何使用Python实现一个简单的window任务管理器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 任务管理器效果图完整代码import tkinter as tkfrom tkinter i

Linux系统中配置静态IP地址的详细步骤

《Linux系统中配置静态IP地址的详细步骤》本文详细介绍了在Linux系统中配置静态IP地址的五个步骤,包括打开终端、编辑网络配置文件、配置IP地址、保存并重启网络服务,这对于系统管理员和新手都极具... 目录步骤一:打开终端步骤二:编辑网络配置文件步骤三:配置静态IP地址步骤四:保存并关闭文件步骤五:重

Windows系统下如何查找JDK的安装路径

《Windows系统下如何查找JDK的安装路径》:本文主要介绍Windows系统下如何查找JDK的安装路径,文中介绍了三种方法,分别是通过命令行检查、使用verbose选项查找jre目录、以及查看... 目录一、确认是否安装了JDK二、查找路径三、另外一种方式如果很久之前安装了JDK,或者在别人的电脑上,想

Python中Windows和macOS文件路径格式不一致的解决方法

《Python中Windows和macOS文件路径格式不一致的解决方法》在Python中,Windows和macOS的文件路径字符串格式不一致主要体现在路径分隔符上,这种差异可能导致跨平台代码在处理文... 目录方法 1:使用 os.path 模块方法 2:使用 pathlib 模块(推荐)方法 3:统一使