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

如何让Tauri应用在macOS托盘图标上居中显示

解决Tauri macOS窗口相对于托盘图标居中显示的问题

核心思路

要实现窗口固定在屏幕顶部且相对于托盘图标居中,核心是获取托盘图标的屏幕坐标,结合窗口自身尺寸计算居中位置,最后通过window.set_position()完成定位。

步骤1:通过原生API获取托盘图标位置(Rust层)

Tauri未直接提供获取托盘图标位置的API,需调用macOS的AppKit原生接口实现。在src-tauri/src/main.rs中添加以下代码:

#[cfg(target_os = "macos")]
use objc::{class, msg_send, sel, sel_impl};
#[cfg(target_os = "macos")]
use cocoa::base::{id, nil};
#[cfg(target_os = "macos")]
use cocoa::foundation::{NSRect, NSPoint};

#[cfg(target_os = "macos")]
fn get_tray_icon_position() -> Option<(f64, f64)> {
    // 获取系统状态栏实例
    let status_bar = unsafe { msg_send![class!(NSStatusBar), systemStatusBar] };
    // 替换为你的Tauri托盘对应的NSStatusItem实例
    // 若使用tauri-plugin-system-tray,可通过插件handle获取原生实例
    let status_item = unsafe { msg_send![status_bar, statusItemWithLength: -1.0] };
    
    if status_item == nil {
        return None;
    }
    
    let view = unsafe { msg_send![status_item, view] };
    let frame = unsafe { msg_send![view, frame] } as NSRect;
    let main_screen = unsafe { msg_send![class!(NSScreen), mainScreen] };
    let screen_frame = unsafe { msg_send![main_screen, frame] } as NSRect;

    // 转换macOS坐标系(Y轴原点在屏幕左下角,菜单栏在顶部)
    let center_x = frame.origin.x + frame.size.width / 2.0;
    let center_y = screen_frame.size.height - frame.origin.y - frame.size.height / 2.0;
    
    Some((center_x, center_y))
}

步骤2:计算窗口居中位置并绑定托盘点击事件

在App初始化的setup逻辑中,监听托盘点击事件,动态计算并设置窗口位置:

use tauri::{Window, Manager, Position, PhysicalPosition};

fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
    let main_window = app.get_window("main").unwrap();
    let tray_handle = app.tray_handle();

    // 绑定托盘点击的窗口切换逻辑
    tray_handle.on_menu_event(|event| {
        if event.menu_item_id() == "toggle_window" {
            let window = event.window().unwrap();
            let is_visible = window.is_visible().unwrap();

            if is_visible {
                window.hide().unwrap();
            } else {
                #[cfg(target_os = "macos")]
                if let Some((tray_x, tray_y)) = get_tray_icon_position() {
                    let window_size = window.inner_size().unwrap();
                    // 计算窗口居中X坐标:托盘中心X - 窗口宽度/2
                    let target_x = tray_x - window_size.width as f64 / 2.0;
                    // 窗口固定在托盘下方,添加10px偏移避免重叠
                    let target_y = tray_y + 10.0;

                    window.set_position(Position::Physical(PhysicalPosition {
                        x: target_x as i32,
                        y: target_y as i32,
                    })).unwrap();
                }

                window.show().unwrap();
                window.set_focus().unwrap();
            }
        }
    });

    Ok(())
}

步骤3:配置窗口基础属性

在tauri.conf.json中设置窗口为无边框、置顶,符合需求样式:

{
  "tauri": {
    "windows": [
      {
        "title": "Your App",
        "width": 300,
        "height": 400,
        "decorations": false,
        "alwaysOnTop": true,
        "skipTaskbar": true
      }
    ]
  }
}

关键注意事项

  • macOS坐标系特殊,Y轴原点在屏幕左下角,计算时需用屏幕总高度减去托盘的Y坐标完成转换。
  • 若其他应用增减托盘项导致图标位置变化,可通过AppKit的NSStatusBar监听状态栏变化事件,重新计算窗口位置。
  • 使用tauri-plugin-system-tray时,需确保插件版本兼容,通过插件的handle正确获取原生NSStatusItem实例。

内容的提问来源于stack exchange,提问作者Boguz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:55:30