7.3 系统深集成:托盘、通知与全局快捷键


标准件仓库的收官三件是"存在感"件:托盘让应用关窗不离场,通知让应用会开口说话,全局快捷键让应用随叫随到。本节把三件的实现各装到位,重点完成一个组合需求——"点关闭进托盘、托盘唤回、快捷键呼出"的常驻型应用。读完本节,随身笔记从窗口应用升级为桌面常驻应用。

托盘:图标、菜单与事件

托盘是纯芯侧能力(tao 的窗口体系负责),在 2.4 的 Setup 钩子里装配最合适:

use tauri::{ menu::{Menu, MenuItem}, tray::{TrayIconBuilder, TrayIconEvent}, Manager, }; pub fn run() { tauri::Builder::default() .setup(|app| { let show = MenuItem::with_id(app, "show", "显示主窗口", true, None::<&str>)?; let quit = MenuItem::with_id(app, "quit", "退出", true, None::<&str>)?; let menu = Menu::with_items(app, &[&show, &quit])?; TrayIconBuilder::with_id("main-tray") .icon(app.default_window_icon().unwrap().clone()) .tooltip("随身笔记") .menu(&menu) .on_menu_event(|app, event| match event.id.as_ref() { "show" => { if let Some(w) = app.get_webview_window("main") { let _ = w.show(); let _ = w.unminimize(); let _ = w.set_focus(); } } "quit" => { app.exit(0); } _ => {} }) .on_tray_icon_event(|tray, event| { if let TrayIconEvent::Click { button: tauri::tray::MouseButton::Left, .. } = event { let app = tray.app_handle(); if let Some(w) = app.get_webview_window("main") { let _ = w.show(); let _ = w.set_focus(); } } }) .build(app)?; Ok(()) }) .run(tauri::generate_context!()) .unwrap(); }

三块积木认一下:菜单项带 id,点击事件按 id 分发;左键单击走 on_tray_icon_event,直接唤窗(平台惯例:Windows 左键唤出、macOS 左键弹菜单——macOS 上把行为挂到菜单项更符合习惯,条件编译分流);图标取默认窗口图标,构建配置里的图标全家桶在这里复用。Linux 上托盘依赖 3.1 装的 appindicator 库——缺库的报错在启动时就暴露,备料的账这会儿结清。

关闭进托盘:与 2.4 拦截的组合

常驻语义的落地是"关闭窗口 ≠ 退出应用"。2.4 的 CloseRequested 拦截在这里变招:不弹确认,改为隐藏:

.on_window_event(|window, event| match event { tauri::WindowEvent::CloseRequested { api, .. } => { // 常驻模式:关闭即隐藏,托盘退出才是真退出 api.prevent_close(); let _ = window.hide(); } _ => {} })

配套的产品细节别漏:首次隐藏时给一条通知(见下文通知件)告诉用户"已最小化到托盘"——这个提示是常驻应用口碑的分水岭,没有它用户以为应用闪退了;设置里留"彻底退出"入口——隐藏语义强到找不到退出按钮的应用会被记恨;托盘 tooltip 与菜单文案里写清当前状态。

通知:会说话的最小实现

官方 notification 插件三步接(四动作照 7.1):

import { isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/plugin-notification'; export async function notify(body: string, title = '随身笔记') { let granted = await isPermissionGranted(); if (!granted) granted = (await requestPermission()) === 'granted'; if (granted) sendNotification({ title, body }); }

使用场景克制:同步完成、保存成功这类"用户不在盯着"的事件值得通知;界面内本来就有反馈的操作别发通知——通知滥用是应用被关通知权限的最快路径。

全局快捷键:随叫随到

global-shortcut 插件注册系统级快捷键(应用不在前台也生效):

import { register, unregister } from '@tauri-apps/plugin-global-shortcut'; await register('CommandOrControl+Shift+N', (event) => { if (event.state === 'Pressed') { invoke('toggle_main_window'); // 呼出或隐藏主窗,芯侧实现切换 } }); // 窗口销毁或设置关闭时务必注销 await unregister('CommandOrControl+Shift+N');

芯侧的 toggle 命令一行逻辑:主窗可见则隐藏、不可见则唤起。三条纪律:组合键避免系统占用(CommandOrControl+Shift 加字母是安全区,单键与系统组合别碰);注册可失败——键位被占时 register 会报错,向用户提示换键而不是默默失效;随生命周期注销——窗口销毁、插件停用时 unregister,否则残留注册到进程退出。

三件联调:一个常驻应用的验收单

把本节三件与 2.4 时序拼成验收单,逐项过:启动出窗、关闭隐藏且通知提示、托盘左键唤回、托盘菜单退出真退出、快捷键呼出再按隐藏、通知权限被拒时应用不崩只静默。这份单子同时是权限清单的核对表——托盘与窗口管理走芯无需发卡,通知与快捷键的插件权限按 6.2 补进清单。

本节要点回顾

  • 托盘三积木:带 id 菜单、菜单事件分发、图标单击唤窗;Linux 依赖 appindicator;
  • 常驻语义:CloseRequested 里 prevent_close 加 hide,真退出只留托盘菜单一处;
  • 首次隐藏发通知:告诉用户"还在托盘里",防"闪退"误会;
  • 通知克制用:只给"用户没盯着"的事件;
  • 快捷键三纪律:避让系统组合、注册失败要可见、随生命周期注销。

仓库领完,应用成型。下一章出厂:构建流水线、安装包瘦身、自动更新与性能——把成品交给用户。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U