Flutter開發(fā)windows應用手記(一)

序言

一直做移動app開發(fā),最近項目需要,著手第一個windows應用開發(fā),從0到1,算是邊學邊用吧。
首先做技術(shù)分析,開發(fā)windows應用最常用的方案,便是microsoft官方的visualStudio,github上許多項目都是采用vs加C#開發(fā)的,由于自己的技術(shù)儲備是Flutter,而flutter官方是支持桌面應用開發(fā)的,所以更加傾向于選擇flutter.
網(wǎng)上查了個遍,關(guān)于flutter開發(fā)桌面應用的博文太少了??吹綆灼际桥f版本的,根本用不了,于是選擇走官方文檔路線。

新手上路

  1. 依據(jù)官方文檔,安裝開發(fā)環(huán)境。

Windows 的額外要求
要開發(fā) Windows 桌面程序,除了 Flutter SDK,你還需要做以下準備:

  • Visual Studio 2022Visual Studio 2022 生成工具 在選擇安裝 Visual Studio 時或只安裝生成工具的時候,你需要選擇「使用 C++ 的桌面開發(fā)」,包括其所有默認組件,以安裝必要的 C++ 工具鏈和 Windows SDK 的頭文件。
  1. 創(chuàng)建一個包含桌面支持的新應用
flutter create my_app
# 根目錄下
cd my_app
flutter run -d windows
# flutter run -d macos
  1. 為已有的應用添加桌面支持
#從項目根目錄在控制臺運行下面命令:
 flutter create --platforms=windows,macos,linux .

設(shè)置創(chuàng)建窗口屬性

  1. windows/runner/main.cpp文件中:
  int screenWidth = GetSystemMetrics(SM_CXSCREEN);   // 獲取屏幕寬度
  int screenHeight = GetSystemMetrics(SM_CYSCREEN);  // 獲取屏幕高度

  FlutterWindow window(project);
  Win32Window::Point origin(screenWidth/2 - 600, screenHeight/2 - 350);
  Win32Window::Size size(1200, 700);

  if (!window.CreateAndShow(chineseString, origin, size)) {
    return EXIT_FAILURE;
  }
  window.SetQuitOnClose(true);

  // 將窗口置于前臺
  SetForegroundWindow(window.GetHandle());
  1. pubspec.yaml文件中引入window_manager(窗口管理庫)和system_tray(管理右下角狀態(tài)欄圖標):
dependencies:
  flutter:
    sdk: flutter
  get: ^4.6.5
  rxdart: ^0.27.3
  path_provider: ^2.0.11
  connectivity_plus: ^5.0.1
  logger: ^1.1.0
  intl: ^0.18.0
  flutter_localization: ^0.1.12
  flutter_phoenix: ^1.1.1
  dio: ^5.1.1
  dio_cache_interceptor: ^3.4.2
  shared_preferences: ^2.0.8
  encrypt: ^5.0.1
  pull_to_refresh: ^2.0.0
  lottie: ^1.4.1
  fast_cached_network_image: ^1.2.0
  flutter_widget_from_html_core: ^0.10.3
  qr_flutter: ^4.1.0
  dart_ping: ^9.0.0
  auto_size_text: ^3.0.0
  url_launcher: ^6.1.12
  image_picker: ^1.0.1
  crop_image: ^1.0.10
  image_compression: ^1.0.4
  package_info_plus: ^4.1.0
  clipboard: ^0.1.3
  file_picker: ^6.1.1
  window_manager: ^0.3.4
  system_tray: ^2.0.3
  1. 創(chuàng)建基類baseApp:
class BaseApp extends StatefulWidget {
  const BaseApp({Key? key}) : super(key: key);

  @override
  State<BaseApp> createState() => _BaseAppState();
}

class _BaseAppState extends State<BaseApp> with WidgetsBindingObserver {
  @override
  Widget build(BuildContext context) {
    // 見window_manager官方文檔
    final virtualWindowFrameBuilder = VirtualWindowFrameInit();

    return RefreshConfiguration(
      hideFooterWhenNotFull: false, // Viewport不滿一屏時,禁用上拉加載更多功能
      enableBallisticLoad: true, // 可以通過慣性滑動觸發(fā)加載更多
      child: GetMaterialApp(
        scrollBehavior: MyCustomScrollBehavior(),
        debugShowCheckedModeBanner: false,
        initialRoute: AppPages.initial,
        getPages: AppPages.routes,
        builder: (context, child) {
          child = virtualWindowFrameBuilder(context, child);
          return child;
        },
        //home: const SizedBox(),
      ),
    );
  }
}
class MyCustomScrollBehavior extends MaterialScrollBehavior {
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
      };
}
  1. lib/main.dart文件中:
import 'package:fast_cached_network_image/fast_cached_network_image.dart';
import 'package:flutter/material.dart';

import 'package:window_manager/window_manager.dart';

import 'base/base_app.dart';
import 'common/global.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Global.init();
  // 初始化網(wǎng)絡(luò)圖片緩存時間
  await FastCachedImageConfig.init(clearCacheAfter: const Duration(days: 1));
  await windowManager.ensureInitialized();
  WindowOptions windowOptions = const WindowOptions(
    size: Size(1200, 700),
    backgroundColor: Colors.transparent,
    skipTaskbar: false,
    titleBarStyle: TitleBarStyle.hidden,
    title: "軟件名稱",
    windowButtonVisibility: false,
    // alwaysOnTop: true,
    center: true,
  );
  windowManager.waitUntilReadyToShow(windowOptions, () async {
    windowManager.setAsFrameless(); //無邊框
    windowManager.setHasShadow(false); //這里不能有陰影,否則會出現(xiàn)一個透明外框
    windowManager.setMaximizable(false);
    windowManager.setResizable(false);
    // windowManager.setAlwaysOnTop(true); //始終置于其它應用上層
    await windowManager.show();
    await windowManager.focus();
  });
  runApp(const BaseApp());
}

至此,一個基本框架已經(jīng)搭建好了,運行目標選擇Windows(desktop),即可看到效果。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容