<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      flutter3-macOS桌面端os系統|flutter3.x+window_manager仿mac桌面管理

      原創力作flutter3+getX+window_manager仿Mac桌面系統平臺Flutter-MacOS

      flutter3_macui基于最新跨端技術flutter3.19+dart3.3+window_manager+system_tray構建的一款桌面端仿MacOS風格os系統項目。支持自定義主題換膚、毛玻璃虛化背景、程序塢Dock菜單多級嵌套+自由拖拽排序、可拖拽路由彈窗等功能。

      2025最新版Flutter3.32桌面端os管理系統。

      Flutter3-MacOS桌面OS系統|flutter3.32+window_manager客戶端OS模板

      FlutterMacOS系統是自研原創多級菜單、支持可拖拽彈窗打開路由頁面模板。

      使用技術

      • 編輯器: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. 桌面菜單支持JSON配置/二級彈窗菜單
      2. 采用ios虛化毛玻璃背景效果
      3. 經典程序塢Dock菜單
      4. 程序塢Dock菜單可拖拽式排序、支持二級彈窗式菜單
      5. 豐富視覺效果,自定義桌面主題換膚背景
      6. 可視化多窗口路由,支持彈窗方式打開新路由頁面
      7. 自定義路由彈窗支持全屏、自由拖拽
      8. 支持macOS和windows 11兩種風格Dock菜單

      項目結構

      通過 flutter create flutter_macos 命令即可快速創建一個flutter空項目模板。

      通過 flutter run -d windows 命令即可運行到windows桌面。

      在開始開發項目之前,需要自己配置好flutter sdk開發環境。具體配置大家可以去官網查閱資料,有詳細的配置步驟。

      Flutter3桌面os布局模板

      桌面os布局整體分為頂部導航條+桌面菜單+底部Dock菜單三大模塊。

      return Scaffold(
        key: scaffoldKey,
        body: Container(
          // 背景圖主題
          decoration: skinTheme(),
          // DragToResizeArea自定義縮放窗口
          child: DragToResizeArea(
            child: Flex(
              direction: Axis.vertical,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // 導航欄
                WindowTitlebar(
                  onDrawer: () {
                    // 自定義打開右側drawer
                    scaffoldKey.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(),
        ),
      );

      Flutter3實現程序塢Dock菜單

      底部Dock菜單支持macOSwindows11兩種風格。采用毛玻璃虛化背景、支持拖拽排序二級彈窗菜單。

      鼠標滑過圖標,該圖標帶動畫效果放大,采用 MouseRegion 和 ScaleTransition 縮放動畫組件一起實現功能。

      // 動畫控制器
      late AnimationController controller = AnimationController(duration: const Duration(milliseconds: 300), vsync: this);
      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),
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      )

      菜單JSON格式配置項,圖標支持Icon圖標Image圖片

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

      二級菜單采用showDialog組件實現三列排版,支持背景虛化、可滾動列表。定位采用Positioned組件實現功能。

      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: () {
                                        // ...
                                      },
                                    ),
                                  );
                                }),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            );
          },
        );
      }

      Flutter實現桌面多級菜單

      桌面菜單采用 Wrap 組件豎向排列顯示。

      @override
      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(
                    ...
                  ),
                ),
              );
            }),
          ),
        );
      }

      桌面菜單縮略二級彈窗菜單和Dock菜單實現思路差不多。點擊桌面菜單通過彈窗方式顯示配置的頁面。

      /**
        桌面彈窗式路由頁面  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配置和Dock菜單配置差不多,只不過多了componentdialog兩個參數。component參數是彈窗打開需要顯示的頁面,dialog是自定義彈窗配置參數。

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

      好了,綜上就是flutter3+window_manager實戰桌面端仿MacOS系統的一些分享,希望對大家有所幫助!

      附上最近兩個實例項目

      http://www.rzrgm.cn/xiaoyan2017/p/17938517

      http://www.rzrgm.cn/xiaoyan2017/p/18048244

       

      posted @ 2024-04-12 21:39  xiaoyan2017  閱讀(1485)  評論(3)    收藏  舉報
      友情鏈接: UP主小店B站
      主站蜘蛛池模板: 99久久er热在这里只有精品99| 老司机亚洲精品一区二区| 乐清市| 国产一区精品综亚洲av| 国99久9在线 | 免费| 精品人妻久久久久久888| 亚洲人妻中文字幕一区| av色蜜桃一区二区三区| 少妇又爽又刺激视频| 国产日韩精品欧美一区喷水| 少妇熟女天堂网av| 日韩有码av中文字幕| 在线A级毛片无码免费真人| 日韩有码国产精品一区| 影音先锋大黄瓜视频| 亚洲日韩久热中文字幕| 免费人成年激情视频在线观看| 四虎成人精品永久免费av| 亚洲综合精品第一页| 欲色欲色天天天www| 男女啪啪免费观看网站| 国产绿帽在线视频看| 欧美一区二区三区成人久久片| 国产精品先锋资源在线看| 护士的小嫩嫩好紧好爽| 亚洲鸥美日韩精品久久| 国产又爽又黄的精品视频| 亚洲欧洲日产国码高潮αv| 久久久久免费看成人影片| 2018av天堂在线视频精品观看 | 国产黄色av一区二区三区| 国产爆乳乱码女大生Av| 一本av高清一区二区三区| 人人做人人澡人人人爽| 麻豆人妻| 国产精品中文字幕免费| 亚洲av日韩av永久无码电影| 熟妇无码熟妇毛片| 国产老熟女狂叫对白| 久热久热中文字幕综合激情| 欧美成人精品三级网站|