如何使用Tauri实现自定义托盘?(原Electron用户咨询)
Tauri实现自定义托盘(替代Electron式窗口化托盘)
完全可以实现类似Electron的自定义组件托盘效果,Tauri通过系统托盘API + 无边框透明窗口的组合,就能打造带自定义UI的托盘弹窗。以下是具体实现步骤:
1. 配置系统托盘基础
首先在Rust后端初始化系统托盘,绑定点击事件来触发自定义窗口的显示/隐藏:
use tauri::{Manager, SystemTray, SystemTrayMenu, SystemTrayMenuItem, PhysicalPosition, Position}; fn main() { // 构建托盘菜单(可选,也可以只靠左键点击触发) let tray_menu = SystemTrayMenu::new() .add_item(SystemTrayMenuItem::new("打开面板", "tray-open")) .add_item(SystemTrayMenuItem::quit("退出应用")); tauri::Builder::default() // 注册系统托盘 .system_tray(SystemTray::new().with_menu(tray_menu)) // 监听托盘事件 .on_system_tray_event(|app, event| match event { // 菜单点击事件 tauri::SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() { "tray-open" => toggle_tray_panel(app), _ => {} }, // 左键点击托盘图标触发显示/隐藏 tauri::SystemTrayEvent::LeftClick { .. } => toggle_tray_panel(app), _ => {} }) // 注册前端调用的命令 .invoke_handler(tauri::generate_handler![show_main_window, quit_app]) .run(tauri::generate_context!()) .expect("启动Tauri应用失败"); } // 封装托盘窗口显示/隐藏逻辑 fn toggle_tray_panel(app: &tauri::AppHandle) { let window = app.get_window("tray-panel").unwrap(); let tray_handle = app.tray_handle(); if window.is_visible().unwrap() { window.hide().unwrap(); } else { // 获取托盘图标位置,让窗口对齐托盘 if let Some(position) = tray_handle.get_position() { // 根据窗口尺寸调整位置,避免超出屏幕(示例窗口宽300,高400) window.set_position(Position::Physical(PhysicalPosition { x: position.x - 150, y: position.y - 400, })).unwrap(); } window.show().unwrap(); window.set_focus().unwrap(); } } // 前端调用的命令:显示主窗口 #[tauri::command] fn show_main_window(app: tauri::AppHandle) { let main_window = app.get_window("main").unwrap(); main_window.show().unwrap(); main_window.set_focus().unwrap(); } // 前端调用的命令:退出应用 #[tauri::command] fn quit_app(app: tauri::AppHandle) { app.exit(0); }
2. 配置自定义托盘窗口
在tauri.conf.json中添加一个无边框、透明、隐藏的窗口,作为托盘的弹窗容器:
{ "tauri": { "windows": [ { "label": "main", "title": "主应用窗口", "width": 800, "height": 600 }, { "label": "tray-panel", "title": "托盘面板", "width": 300, "height": 400, "decorations": false, // 去掉窗口边框 "transparent": true, // 开启透明背景 "alwaysOnTop": true, // 窗口置顶 "skipTaskbar": true, // 不在任务栏显示 "visible": false // 默认隐藏 } ] } }
3. 实现前端自定义组件
创建对应的托盘窗口页面(比如src/tray.html),编写自定义UI和交互逻辑:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { background: #2d3748; border-radius: 8px; padding: 16px; color: #f7fafc; font-family: system-ui, -apple-system, sans-serif; } .tray-menu { display: flex; flex-direction: column; gap: 8px; } .menu-item { padding: 10px 12px; border-radius: 4px; cursor: pointer; transition: background 0.2s; } .menu-item:hover { background: #4a5568; } .divider { height: 1px; background: #4a5568; margin: 8px 0; } </style> </head> <body> <div class="tray-menu"> <div class="menu-item" onclick="showMainWindow()">打开主窗口</div> <div class="divider"></div> <div class="menu-item" onclick="quitApp()">退出应用</div> </div> <script> import { invoke, window } from '@tauri-apps/api'; // 点击窗口外部隐藏托盘面板 document.addEventListener('click', (e) => { if (e.target === document.body) { window.getCurrentWindow().hide(); } }); // 调用后端命令显示主窗口 async function showMainWindow() { await invoke('show_main_window'); window.getCurrentWindow().hide(); } // 调用后端命令退出应用 async function quitApp() { await invoke('quit_app'); } </script> </body> </html>
注意事项
- 窗口位置调整:不同系统的托盘位置逻辑不同(比如Windows托盘在底部,macOS可能在顶部),可以根据系统类型动态调整窗口位置。
- 性能优化:透明窗口可能在部分系统有性能损耗,建议控制窗口尺寸不要过大。
- 跨系统兼容:测试时要覆盖Windows、macOS和Linux,确保托盘行为一致。
内容的提问来源于stack exchange,提问作者Matan Shushan
相关产品推荐
相关产品推荐

