系统托盘:系统托盘是一种用户界面元素,通常出现在操作系统的任务栏或桌面顶部。它是一个水平的狭长区域,用于显示各种图标和通知,以提供快速访问和操作特定应用程序或系统功能。系统托盘通常包含操作系统或第三方应用程序的图标,这些图标可以显示有关应用程序状态、提醒和通知等信息。用户可以通过单击这些图标来打开应用程序的主窗口、执行特定功能或查看详细信息。系统托盘的设计旨在提供一种方便的方式来管理和访问常用的应用程序和系统功能,以提高用户的工作效率。
效果展示
作为现代操作系统中常见的一个组件,系统托盘能够让用户方便地访问常用的应用程序或者系统功能。对于Flutter桌面应用程序开发者来说,如何在应用程序中定义系统托盘是一个值得探讨的问题。本文将简介系统托盘的概念,并介绍两种可用的Flutter桌面应用程序系统托盘方案。
tray_manager
Windows, macOS & Linux
dependencies:
...
tray_manager: ^0.2.0
import 'package:flutter/material.dart' hide MenuItem;
import 'package:tray_manager/tray_manager.dart';
Future<void> _init() async {
//设置系统托盘图标,Windows图标必须文件后缀必须是.ico
await trayManager.setIcon(
Platform.isWindows
? 'assets/images/tray_icon_original.ico'
: 'assets/images/img_1.png',
);
//设置系统托盘的标题
trayManager.setTitle("system tray");
//设置系统托盘的标题
trayManager.setToolTip("How to use system tray with Flutter:鼠标滑过提示");
//设置系统托盘的菜单
Menu menu = Menu(
items: [
//设置系统托盘的子菜单
MenuItem.submenu(
// key
key: 'window_settings',
label: '窗口设置',
//trayManager 不支持菜单项添加图标,该配置无效
icon: Platform.isWindows
? 'assets/images/app_icon.bmp'
: 'assets/images/img_1.png',
submenu: Menu(items: [
MenuItem.checkbox(
checked: true,
label: "毛玻璃效果",
onClick: (MenuItem menuItem) {
menuItem.checked = !(menuItem.checked == true);
if (kDebugMode) {
print("毛玻璃效果 onClick ${menuItem.checked}");
}
},
),
MenuItem.checkbox(
checked: true,
label: "窗口置顶",
onClick: (MenuItem menuItem) {
menuItem.checked = !(menuItem.checked == true);
if (kDebugMode) {
print("窗口置顶 onClick ${menuItem.checked}");
}
},
),
MenuItem.checkbox(
checked: true,
label: "自启动",
onClick: (MenuItem menuItem) {
menuItem.checked = !(menuItem.checked == true);
if (kDebugMode) {
print("自启动 onClick ${menuItem.checked}");
}
},
),
//可选类型的菜单栏
MenuItem.checkbox(
checked: true,
label: "图标闪烁",
onClick: (MenuItem menuItem) {
menuItem.checked = !(menuItem.checked == true);
if (kDebugMode) {
print("图标闪烁 onClick ${menuItem.checked}");
}
},
),
])),
//分割线
MenuItem.separator(),
MenuItem(
key: 'open_app',
label: 'Open App',
onClick: (MenuItem menuItem) {
}),
MenuItem(
key: 'exit_app',
label: 'Exit App',
onClick: (MenuItem menuItem) {
}),
],
);
if (kDebugMode) {
print("menu:${menu.toJson()}");
}
//为系统托盘配置菜单
await trayManager.setContextMenu(menu);
}
import 'package:flutter/material.dart';
import 'package:tray_manager/tray_manager.dart';
class HomePage extends StatefulWidget {
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with TrayListener {
void initState() {
trayManager.addListener(this);
super.initState();
_init();
}
void dispose() {
trayManager.removeListener(this);
super.dispose();
}
void _init() {
// ...
}
Widget build(BuildContext context) {
// ...
}
//未触发该事件
void onTrayIconRightMouseUp() {
// TODO: implement onTrayIconRightMouseUp
super.onTrayIconRightMouseUp();
if (kDebugMode) {
print("onTrayIconMouseUp");
}
}
//未触发该事件
void onTrayIconMouseUp() {
super.onTrayIconMouseUp();
if (kDebugMode) {
print("onTrayIconMouseUp");
}
}
void onTrayIconMouseDown() {
if (kDebugMode) {
print("onTrayIconMouseDown");
}
//弹出托盘的菜单栏
trayManager.popUpContextMenu();
}
void onTrayIconRightMouseDown() {
if (kDebugMode) {
print("onTrayIconRightMouseDown");
}
//弹出托盘的菜单栏
trayManager.popUpContextMenu();
}
//弹出托盘的菜单栏点击事件
void onTrayMenuItemClick(MenuItem menuItem) {
if (kDebugMode) {
print("menuItem:${menuItem.key}-${menuItem.label}");
}
}
}
system_tray
Windows, macOS & Linux
dependencies:
...
system_tray: ^2.0.3
import 'package:system_tray/system_tray.dart';
//创建SystemTray 对象
final SystemTray _systemTray = SystemTray();
Timer? _timer;
//配置系统托盘
Future<void> _initSystemTray() async {
//设置系统托盘的图标,必须是.ico后缀的图片
await _systemTray.initSystemTray(
iconPath: Platform.isWindows
? 'assets/images/tray_icon_original.ico'
: 'assets/images/img_1.png',
);
//设置系统托盘的标题
_systemTray.setTitle("system tray");
//设置系统托盘的提示
_systemTray.setToolTip("How to use system tray with Flutter");
//注册系统托盘事件
_systemTray.registerSystemTrayEventHandler((eventName) {
debugPrint("eventName: $eventName");
//注册系统托盘事件:点击事件
if (eventName == kSystemTrayEventClick) {
//Windows系统:显示主窗口 其他系统弹出托盘菜单弹框
Platform.isWindows
? windowManager.show()
: _systemTray.popUpContextMenu();
//注册系统托盘事件:鼠键右键
} else if (eventName == kSystemTrayEventRightClick) {
//Windows系统:弹出托盘菜单弹框 其他系统: 显示主窗口
Platform.isWindows
? _systemTray.popUpContextMenu()
: windowManager.show();
}
});
//创建托盘的菜单
final Menu _menuMain = Menu();
await _menuMain.buildFrom([
//创建子菜单
SubMenu(
label: "窗口设置",
//创建为菜单子项添加图标,格式必须是bmp
image: Platform.isWindows
? 'assets/images/app_icon.bmp'
: 'assets/images/img_1.png',
children: [
//创建可选框类型的菜单项
MenuItemCheckbox(
label: "毛玻璃效果",
checked: true,
name: 'acrylic_cb',
onClicked: (MenuItemBase menuItem) async {
//更新MenuItemCheckbox的状态
await menuItem.setCheck(!menuItem.checked);
if (kDebugMode) {
print("毛玻璃效果 onClick ${menuItem.checked}");
}
if (menuItem.checked == true) {
showAcrylic(color);
} else {
closeAcrylic();
}
}),
MenuItemCheckbox(
label: "窗口置顶",
checked: true,
onClicked: (MenuItemBase menuItem) async {
await menuItem.setCheck(!menuItem.checked);
if (kDebugMode) {
print("窗口置顶 onClick ${menuItem.checked}");
}
if (menuItem.checked == true) {
windowManager.setAlwaysOnTop(true);
} else {
windowManager.setAlwaysOnTop(false);
}
}),
MenuItemCheckbox(
label: "自启动",
checked: true,
name: 'auto_start_cb',
onClicked: (MenuItemBase menuItem) async {
// menuItem.checked = !(menuItem.checked == true);
await menuItem.setCheck(!menuItem.checked);
if (kDebugMode) {
print("自启动 onClick ${menuItem.checked}");
}
}),
MenuItemCheckbox(
label: "图标闪烁",
checked: true,
name: "flash_cb",
onClicked: (MenuItemBase menuItem) async {
MenuItemCheckbox? flashCb =
_menuMain.findItemByName<MenuItemCheckbox>("flash_cb");
await flashCb?.setCheck(!menuItem.checked);
if (kDebugMode) {
print("图标闪烁 onClick ${menuItem.checked}");
}
if (menuItem.checked) {
startFlashIcon();
} else {
stopFlashIcon();
}
}),
]),
//菜单分割线
MenuSeparator(),
//菜单项
MenuItemLabel(
label: 'Open App',
image: Platform.isWindows
? 'assets/images/app_icon.bmp'
: 'assets/images/img_1.png',
onClicked: (MenuItemBase menuItem) {
windowManager.show();
}),
MenuItemLabel(
label: 'Exit App',
image: Platform.isWindows
? 'assets/images/app_icon.bmp'
: 'assets/images/img_1.png',
onClicked: (MenuItemBase menuItem) {
windowManager.close();
}),
]);
if (kDebugMode) {
print("menu:${_menuMain.toString()}");
}
//为系统托盘设置菜单项
await _systemTray.setContextMenu(_menuMain);
}
import 'package:flutter/material.dart';
import 'package:tray_manager/tray_manager.dart';
class HomePage extends StatefulWidget {
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Timer? _timer;
final SystemTray _systemTray = SystemTray();
void initState() {
super.initState();
_initSystemTray();
}
void dispose() {
_timer.cancel();
super.dispose();
}
void _initSystemTray() {
// ...
}
//开始图标闪烁
void startFlashIcon() {
if (kDebugMode) {
print("startFlashIcon");
}
var imageList = const [
"assets/images/tray_icon_original.ico",
"assets/images/tray_icon.ico"
];
var index = 0;
_timer =
Timer.periodic(const Duration(milliseconds: 500), (Timer timer) async {
if (kDebugMode) {
print("path:${imageList[index]}");
}
await _systemTray.setImage(imageList[index]);
index = (index == 0) ? 1 : 0;
});
}
//停止图标闪烁
void stopFlashIcon() async {
if (kDebugMode) {
print("stopFlashIcon");
}
_timer?.cancel();
_timer = null;
await _systemTray.setImage("assets/images/tray_icon_original.ico");
}
Widget build(BuildContext context) {
// ...
}
}
system_tray 支持菜单项添加图标,tray_manager不支持菜单项添加图标
Windows平台系统托盘图标需要是以.ico后缀的图片,菜单项图标需要是.bmp后缀的图片,否则图片无法显示;