问题背景
在我们的工作生活中,越来越离不开手机,出门也必是标配。我们时常需要在外办公,无奈没有很nice的手机OA办公系统。于是flutter-osx项目就应运而生了。全新原创研发的手机桌面式os系统管理新模式。
经过半个多月爆肝开发,我的又一款原创作品flutter3-osx手机桌面os管理系统正式完结了。
全新手机桌面式OA管理系统新解决方案。通过最少的配置,即可像操作手机应用一样操作页面。
前段时间有分享一款vue3+uniapp跨端手机os实例项目,如果感兴趣也可以去瞅瞅~
https://developer.aliyun.com/article/1534540
使用技术
- 编辑器:vscode
- 技术框架:flutter3.22.1+dart3.4.1
- 路由/状态管理:get^4.6.6
- 本地存储:get_storage^2.1.1
- svg图片插件:flutter_svg^2.0.10+1
- 图表组件:fl_chart^0.68.0
- 国际化时间:intl^0.19.0
同样支持编译运行到windows端,效果依然perfect!
项目结构
采用最新版Flutter3.22开发搭建项目模板。
采用滑动数字解锁新模式。
使用 AnimatedSwitcher 和 FadeTransition 小部件来实现切换动画效果。
@override Widget build(BuildContext context) { return Layout( extendBodyBehindAppBar: true, body: Container( padding: const EdgeInsets.all(20.0), child: AnimatedSwitcher( duration: const Duration(milliseconds: 250), // 动画控制 transitionBuilder: (child, animation) { return FadeTransition( opacity: animation, child: ScaleTransition( // scale: animation, scale: animation.drive(Tween(begin: 0.9, end: 1.0).chain(CurveTween(curve: Curves.easeOut))), child: child, ), ); }, // 当内容有变化的时候就会触发动画 child: splashScreen ? GestureDetector( // 修复Column和Row组件,点击空白处无响应问题 behavior: HitTestBehavior.translucent, child: Column( children: [ ], ), onPanStart: (details) { setState(() { swipeY = details.globalPosition.dy; }); }, onPanUpdate: (details) { double posY = swipeY - details.globalPosition.dy; if(posY > 100) { setState(() { splashScreen = false; }); } }, ) : Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ], ), ), ), ), ); }
Column( children: [ const Text('数字密码解锁', style: TextStyle(color: Colors.white, fontSize: 14.0),), const SizedBox(height: 10.0,), Wrap( spacing: 15.0, children: List.generate(passwordArr.length, (index) { return AnimatedContainer( duration: const Duration(milliseconds: 300), height: 10.0, width: 10.0, decoration: BoxDecoration( color: int.parse(passwordArr[index]) <= pwdValue.length ? Colors.white : Colors.white.withOpacity(0.01), border: Border.all(color: Colors.white), borderRadius: BorderRadius.circular(50.0), ), ); }) ), ], ),
Container( width: 250.0, margin: const EdgeInsets.only(top: 50.0), child: Wrap( spacing: 15.0, runSpacing: 15.0, alignment: WrapAlignment.center, children: List.generate(keyNumbers.length, (index) { return Material( type: MaterialType.transparency, child: Ink( height: 60.0, width: 60.0, decoration: BoxDecoration( color: Colors.white24, border: Border.all(color: Colors.white24, width: .5), borderRadius: BorderRadius.circular(50.0), ), child: InkWell( borderRadius: BorderRadius.circular(50.0), overlayColor: WidgetStateProperty.all(Colors.white38), child: DefaultTextStyle( style: const TextStyle(color: Colors.white, fontFamily: 'arial'), child: Column( children: [ const SizedBox(height: 10.0,), Text(keyNumbers[index]['num'], style: const TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),), Text(keyNumbers[index]['letter'], style: const TextStyle(fontSize: 10.0),), ], ), ), onTap: () { handleClickNum(keyNumbers[index]['num']); }, ), ), ); }) ), ),
运行到桌面端依然保持完美容颜。
flutter-os公共布局
整体桌面分为栅格式菜单+底部Dock菜单+拖拽悬浮球菜单。
@override Widget build(BuildContext context) { return Scaffold( extendBodyBehindAppBar: widget.extendBodyBehindAppBar, appBar: widget.appBar ?? AppBar( forceMaterialTransparency: true, backgroundColor: Colors.transparent, foregroundColor: Colors.white, toolbarHeight: 0, ), body: Center( child: Stack( children: [ // 壁纸皮肤 if(widget.showBackground) Obx(() => Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage('${skinController.skinUrl}'), fit: BoxFit.fill, ), ), )) , Flex( direction: Axis.vertical, crossAxisAlignment: CrossAxisAlignment.start, children: [ // 顶部插槽 Container( child: widget.header, ), // 内容区域 Expanded( child: widget.body ?? Container(), ), // 底部插槽 Container( child: widget.footer, ), ], ), // 额外插槽 Container( child: widget.extra, ), ], ), ), ); }
flutter手机桌面栅格布局
/* * ================== 手机桌面os配置项 ================== * [label] 图标标题 * [imgico] 图标(本地或网络图片) 当type: 'icon'则为uni-icons图标名,当type: 'widget'则为自定义小部件标识名 * [type] 图标类型(icon | widget) icon为uni-icons图标、widget为自定义小部件 * [path] 跳转路由页面 * [link] 跳转外部链接 * [hideLabel] 是否隐藏图标标题 * [background] 自定义图标背景色 * [size] 栅格磁贴布局(16种) 1x1 1x2 1x3 1x4、2x1 2x2 2x3 2x4、3x1 3x2 3x3 3x4、4x1 4x2 4x3 4x4 * [onClick] 点击图标回调函数 */
List flutterDeskMenus = [ { 'uid': '3u85fb90-12c4-11e1-840d-7b25c5ee775a', 'list': [ {'label': 'Flutter3.22', 'imgico': 'assets/images/flutter.png', 'link': 'https://flutter.dev/'}, {'label': 'Dart中文官方文档', 'imgico': 'assets/images/dart.png', 'link': 'https://dart.cn/'}, {'label': '日历', 'imgico': const Calendar1x1(), 'type': 'widget', 'path': '/calendar', 'background': const Color(0xffffffff),}, {'label': '首页', 'imgico': const Icon(Icons.home_outlined), 'type': 'icon', 'path': '/home'}, {'label': '工作台', 'imgico': const Icon(Icons.poll_outlined), 'type': 'icon', 'path': '/workplace'}, { 'label': '组件', 'children': [ {'label': '组件', 'imgico': 'assets/images/svg/component.svg', 'path': '/component'}, ] }, { 'label': '管理中心', 'children': [ {'label': '个人主页', 'imgico': 'assets/images/svg/my.svg', 'path': '/ucenter'}, ] }, { 'label': '编程开发', 'children': [ {'label': 'Github', 'imgico': 'assets/images/svg/github.svg', 'background': const Color(0xff607d8b),}, {'label': 'Flutter', 'imgico': 'assets/images/flutter.png', 'background': const Color(0xFFDAF2FA),}, {'label': 'ChatGPT', 'imgico': 'assets/images/svg/chatgpt.svg', 'background': const Color(0xFF15A17F),}, ] }, { 'label': '关于', 'imgico': const Icon(Icons.info), 'type': 'icon', 'onClick': () => { } }, { 'label': '公众号', 'imgico': const Icon(Icons.qr_code), 'type': 'icon', 'onClick': () => { } }, ] } ];
通过实战开发flutter3-osx项目,探索了一种全新的手机桌面os管理系统解决方案。
当然小伙伴们也可以在此框架上做一些有创意的项目,帮助到更多需要帮助的人。一起为flutter生态添砖加瓦,fighting~~