Flutter Windows桌面端如何实现托盘单击/双击打开/隐藏应用 已按要求输出标题
我在用Flutter开发Windows桌面应用时,想实现系统托盘功能,但遇到一些问题:如何监听托盘图标的单击和双击事件?单击时希望隐藏应用窗口,双击时重新显示窗口。目前尝试了tray_manager和system_tray插件,但都没找到直接支持双击事件的方法。请问有没有成熟的解决方案?或者需要自己编写MethodChannel与原生代码交互?最好能提供具体实现示例。
2 回复
Flutter桌面端可通过system_tray插件实现托盘功能。监听单击/双击事件,调用show()/hide()控制窗口显隐。需注意平台差异,Windows需处理窗口最小化逻辑。
更多关于Flutter Windows桌面端如何实现托盘单击/双击打开/隐藏应用 已按要求输出标题的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
Flutter Windows桌面端实现托盘单击/双击打开/隐藏应用
实现方案
在Flutter Windows桌面端实现托盘功能需要使用system_tray和window_manager插件。
步骤
1. 添加依赖
dependencies:
system_tray: ^2.0.0
window_manager: ^0.3.0
2. 完整实现代码
import 'package:flutter/material.dart';
import 'package:system_tray/system_tray.dart';
import 'package:window_manager/window_manager.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化窗口管理器
await windowManager.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WindowListener {
final SystemTray _systemTray = SystemTray();
final AppWindow _appWindow = AppWindow();
bool _isWindowVisible = true;
@override
void initState() {
super.initState();
_initSystemTray();
windowManager.addListener(this);
}
Future<void> _initSystemTray() async {
// 初始化系统托盘
await _systemTray.initSystemTray(
title: "My App",
iconPath: "assets/app_icon.ico", // 托盘图标路径
);
// 创建托盘菜单
final Menu menu = Menu();
await menu.buildFrom([
MenuItemLabel(
label: '显示/隐藏',
onClicked: _toggleWindowVisibility,
),
MenuSeparator(),
MenuItemLabel(
label: '退出',
onClicked: _exitApp,
),
]);
await _systemTray.setContextMenu(menu);
// 设置托盘点击事件
_systemTray.registerSystemTrayEventHandler((eventName) {
if (eventName == kSystemTrayEventClick) {
// 单击事件
_toggleWindowVisibility();
} else if (eventName == kSystemTrayEventDoubleClick) {
// 双击事件
_toggleWindowVisibility();
}
});
}
void _toggleWindowVisibility() async {
if (_isWindowVisible) {
// 隐藏窗口
await windowManager.hide();
setState(() {
_isWindowVisible = false;
});
} else {
// 显示窗口
await windowManager.show();
await windowManager.focus();
setState(() {
_isWindowVisible = true;
});
}
}
void _exitApp() {
_appWindow.close();
}
@override
void onWindowClose() async {
// 点击关闭按钮时最小化到托盘而不是退出
bool isPreventClose = await windowManager.isPreventClose();
if (isPreventClose) {
await windowManager.hide();
setState(() {
_isWindowVisible = false;
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('托盘示例应用'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('应用主窗口'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _toggleWindowVisibility,
child: Text(_isWindowVisible ? '隐藏到托盘' : '显示窗口'),
),
],
),
),
),
);
}
@override
void dispose() {
windowManager.removeListener(this);
super.dispose();
}
}
3. 配置说明
在windows/runner/main.cpp中设置窗口关闭行为:
// 在窗口创建后添加
window->SetOnCloseRequested([&](winrt::Microsoft::UI::Xaml::Window const&, winrt::Microsoft::UI::Xaml::WindowCloseRequestedEventArgs const& args) {
args.Handled(true); // 阻止默认关闭行为
// 发送消息到Flutter端处理隐藏逻辑
return;
});
功能特点
- 单击托盘图标:切换窗口显示/隐藏
- 双击托盘图标:切换窗口显示/隐藏
- 右键菜单:提供显示/隐藏和退出选项
- 关闭按钮:点击时隐藏到托盘而非退出
注意事项
- 需要准备合适的ICO格式图标文件
- 在Windows平台需要相应的权限配置
- 建议测试不同Windows版本的兼容性
这样就实现了完整的托盘单击/双击打开/隐藏应用功能。

