序言
一直做移動app開發(fā)柠掂,最近項目需要涨颜,著手第一個windows應用開發(fā)费韭,從0到1,算是邊學邊用吧庭瑰。
首先做技術分析星持,開發(fā)windows應用最常用的方案,便是microsoft官方的visualStudio弹灭,github上許多項目都是采用vs加C#開發(fā)的钉汗,由于自己的技術儲備是Flutter,而flutter官方是支持桌面應用開發(fā)的鲤屡,所以更加傾向于選擇flutter.
網(wǎng)上查了個遍损痰,關于flutter開發(fā)桌面應用的博文太少了【评矗看到幾篇都是舊版本的卢未,根本用不了,于是選擇走官方文檔路線堰汉。
新手上路
- 依據(jù)官方文檔辽社,安裝開發(fā)環(huán)境。
Windows 的額外要求
要開發(fā) Windows 桌面程序翘鸭,除了 Flutter SDK滴铅,你還需要做以下準備:
- Visual Studio 2022 或 Visual Studio 2022 生成工具 在選擇安裝 Visual Studio 時或只安裝生成工具的時候,你需要選擇「使用 C++ 的桌面開發(fā)」就乓,包括其所有默認組件汉匙,以安裝必要的 C++ 工具鏈和 Windows SDK 的頭文件。
- 創(chuàng)建一個包含桌面支持的新應用
flutter create my_app
# 根目錄下
cd my_app
flutter run -d windows
# flutter run -d macos
- 為已有的應用添加桌面支持
#從項目根目錄在控制臺運行下面命令:
flutter create --platforms=windows,macos,linux .
設置創(chuàng)建窗口屬性
- 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());
- 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
- 創(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,
};
}
- 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)絡圖片緩存時間
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)邦投,即可看到效果伤锚。