Last Updated on 2024-08-20 by Clay
最近開始嘗試使用 Flutter 來實作桌面的應用程式,由於我是使用 Linux 的 Gnome 桌面,其預設的系統視窗欄(最上面的橫條)是純黑的,與我開發的 APP 其輕鬆活潑的調性不符合,所以這才找了個不錯的套件工具:bitsdojo_window。
這個套件的強大之處在於,它同時支援 Windows、MacOS 和 Linux;但有些麻煩的是,它並不是安裝即可,也需要稍微做一些調整。
bitsdojo_window 的使用方式(主要是 Linux)
- 檢查 bitsdojo_window 的 pub.dev 確認最新版本與語法
- 在 pubspec.yaml 檔案中添加套件
- 修改 linux/my_application.cc
- 測試範例程式碼
Step 1. 檢查 bitsdojo_window 的 pub.dev 確認最新版本與語法
在我這裡,pub.dev 上的 bitsdojo_window 頁面最新版本是 0.1.6,所以我等等就是添加此版本。
Step 2: 在 pubspec.yaml 檔案中添加套件
dependencies:
flutter:
sdk: flutter
bitsdojo_window: ^0.1.6
接著取得套件:
flutter pub get
Step 3: 修改 linux/my_application.cc
在 Linux 上使用 bitsdojo_window
時,我們需要修改 linux/my_application.cc
文件,找到以下程式碼:
gtk_window_set_default_size(window, 1280, 720);
gtk_widget_show(GTK_WIDGET(window));
並將其更改為:
auto bdw = bitsdojo_window_from(window);
bdw->setCustomFrame(true);
// gtk_window_set_default_size(window, 1280, 720); // <-- Comment this line
gtk_widget_show(GTK_WIDGET(window));
這樣可以讓應用程式使用自定義的視窗邊框,而不是系統的標題欄。
除此之外,也別忘了要在這份文件的開頭,確認有無引入 bitsdojo_window_plugin.h
:
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
Step 4: 測試範例程式碼
在這裡我直接執行官方的範例程式碼:
import 'package:flutter/material.dart';
import 'package:bitsdojo_window/bitsdojo_window.dart';
void main() {
runApp(const MyApp());
doWhenWindowReady(() {
final win = appWindow;
const initialSize = Size(600, 450);
win.minSize = initialSize;
win.size = initialSize;
win.alignment = Alignment.center;
win.title = "Custom window with Flutter";
win.show();
});
}
const borderColor = Color(0xFF805306);
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: WindowBorder(
color: borderColor,
width: 1,
child: Row(
children: const [LeftSide(), RightSide()],
),
),
),
);
}
}
const sidebarColor = Color(0xFFF6A00C);
class LeftSide extends StatelessWidget {
const LeftSide({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: 200,
child: Container(
color: sidebarColor,
child: Column(
children: [
WindowTitleBarBox(child: MoveWindow()),
Expanded(child: Container())
],
)));
}
}
const backgroundStartColor = Color(0xFFFFD500);
const backgroundEndColor = Color(0xFFF6A00C);
class RightSide extends StatelessWidget {
const RightSide({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [backgroundStartColor, backgroundEndColor],
stops: [0.0, 1.0]),
),
child: Column(children: [
WindowTitleBarBox(
child: Row(
children: [Expanded(child: MoveWindow()), const WindowButtons()],
),
)
]),
),
);
}
}
final buttonColors = WindowButtonColors(
iconNormal: const Color(0xFF805306),
mouseOver: const Color(0xFFF6A00C),
mouseDown: const Color(0xFF805306),
iconMouseOver: const Color(0xFF805306),
iconMouseDown: const Color(0xFFFFD500));
final closeButtonColors = WindowButtonColors(
mouseOver: const Color(0xFFD32F2F),
mouseDown: const Color(0xFFB71C1C),
iconNormal: const Color(0xFF805306),
iconMouseOver: Colors.white);
class WindowButtons extends StatelessWidget {
const WindowButtons({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: [
MinimizeWindowButton(colors: buttonColors),
MaximizeWindowButton(colors: buttonColors),
CloseWindowButton(colors: closeButtonColors),
],
);
}
}
Output:
可以看到,我們已經用上了自定義的視窗標題欄了!
這對於我接下來要嘗試的美術風格至關重要呢。
References
- https://pub.dev/packages/bitsdojo_window
- How to Remove Title Bar from Flutter app built for windows?