flutter3-weos手機OS系統|Flutter3.22+Getx仿ios桌面管理OA應用

xiaoyan2017發表於2024-06-06

原創自研flutter3.x+getx仿製ios手機桌面UI管理系統模板Flutter3-OS

flutter3-osx基於最新跨平臺技術Flutter3.22+Dart3.4+GetX+fl_chart實戰仿IOS風格手機os管理系統。全新自研flutter磁貼式柵格佈局引擎、分屏式多頁管理、自定義主題桌布、卡片式桌面小部件、可拖拽式懸浮球選單等功能。

全新原創自研的OS柵格化選單佈局引擎,探索flutter手機端管理系統OA新模式

技術棧

  • 編輯器: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

flutter3-os專案在windows端效果依然nice!其實之前也有專門分享一款flutter3仿macOS桌面框架,感興趣的可以去看看。

https://www.cnblogs.com/xiaoyan2017/p/18132176

功能特性

✅ 經典的柵格化佈局+Dock導航模式
✅ 桌面選單JSON配置生成
✅ 支援16種柵格佈局模式
✅ 分屏式多頁管理
✅ 可拖拽懸浮球選單
✅ 毛玻璃虛化背景操作視窗
✅ 豐富的視覺效果,自定義桌面個性桌布
✅ 高定製化自定義桌面小部件

專案結構目錄

使用最新版flutter3.22+dart3.4架構開發,顛覆傳統後臺管理,探索一種全新的手機後臺OA管理系統新模式。

目前該專案已經同步到我的原創作品集,有需要的話,歡迎去瞅瞅~

https://gf.bilibili.com/item/detail/1106107011

入口配置

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:intl/date_symbol_data_local.dart';

import 'utils/index.dart';

// 引入桌面柵格模板
import 'layouts/desk.dart';

// 引入路由管理
import 'router/index.dart';

void main() async {
  // 初始化get_storage本地儲存
  await GetStorage.init();
  // 初始化國際化語言
  initializeDateFormatting();

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter WeOS',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
        // 修復windows端字型粗細不一致
        fontFamily: Platform.isWindows ? 'Microsoft YaHei' : null,
      ),
      home: const DeskLayout(),
      // 初始化路由
      initialRoute: Utils.isLogin() ? '/' : '/launch',
      // 路由頁面
      getPages: routes,
    );
  }
}

動畫式數字密碼登入驗證解鎖新模式。

摒棄傳統的輸入框式登入方式,為了整體效果一致性採用全新數字解鎖驗證模式。

使用 AnimatedSwitcherFadeTransition 配合實現切換動畫效果。

@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: [
              ...
            ],
          ),
        ),
      ),
    ),
  );
}

數字密碼長度可以自定義配置,沒有直接寫死6位。

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']);
            },
          ),
        ),
      );
    })
  ),
),

公共佈局模板Layout

桌面佈局整體分為柵格式選單+底部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選單

桌面os選單配置項

/*
 * ================== 桌面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 deskMenus = [
  ...
  {
    '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': () => {
          ...
        }
      },
    ]
  }
  ...
];

由於該柵格桌面系統涉及到的知識點蠻多的,就不展開詳細的一 一介紹了。希望以上分享對大家有所幫助哈~

最後附上兩個例項專案

https://www.cnblogs.com/xiaoyan2017/p/18165578

https://www.cnblogs.com/xiaoyan2017/p/18092224

相關文章