You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 08:04:55