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

为macOS的MenuBarExtra添加右键上下文菜单(仿Figma行为)

实现macOS MenuBarExtra右键上下文菜单(类似Figma)

SwiftUI 实现方案

如果你的项目基于SwiftUI,可通过结合NSStatusItem实现左键打开窗口、右键弹出上下文菜单的效果:

import SwiftUI

@main
struct MenuBarDemoApp: App {
    private var statusItem: NSStatusItem!
    
    var body: some Scene {
        // 定义MenuBarExtra,使用window样式实现左键打开窗口
        MenuBarExtra("Demo", systemImage: "square") {
            Text("Main Window Content")
                .frame(width: 300, height: 200)
        }
        .menuBarExtraStyle(.window)
        .onAppear {
            // 获取系统状态栏项
            statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
            // 同步状态栏图标
            statusItem.button?.image = NSImage(systemSymbolName: "square", accessibilityDescription: nil)
            
            // 构建右键上下文菜单
            let rightClickMenu = NSMenu()
            rightClickMenu.addItem(NSMenuItem(title: "设置", action: #selector(openSettings), keyEquivalent: ","))
            rightClickMenu.addItem(NSMenuItem.separator())
            rightClickMenu.addItem(NSMenuItem(title: "退出", action: #selector(quitApp), keyEquivalent: "q"))
            
            // 设置按钮响应左右点击事件
            statusItem.button?.sendAction(on: [.leftMouseUp, .rightMouseUp])
            statusItem.menu = rightClickMenu
        }
    }
    
    @objc private func openSettings() {
        // 触发系统设置窗口逻辑
        NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
    }
    
    @objc private func quitApp() {
        NSApp.terminate(nil)
    }
}

关键说明

  • 使用.menuBarExtraStyle(.window)指定左键点击打开窗口
  • 通过NSStatusItem自定义右键菜单,同时设置按钮响应左右点击事件
  • 菜单项可根据需求添加分隔符、快捷键,保持系统交互一致性

AppKit 实现方案

传统AppKit项目可直接通过NSStatusItem实现该交互:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    private var statusItem: NSStatusItem!
    private var mainWindow: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // 创建状态栏项
        statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
        statusItem.button?.image = NSImage(systemSymbolName: "square", accessibilityDescription: nil)
        // 设置按钮响应左右点击
        statusItem.button?.sendAction(on: [.leftMouseUp, .rightMouseUp])
        statusItem.button?.action = #selector(statusBarButtonClicked(_:))
        
        // 构建右键菜单
        let rightClickMenu = NSMenu()
        rightClickMenu.addItem(NSMenuItem(title: "设置", action: #selector(openSettings), keyEquivalent: ","))
        rightClickMenu.addItem(NSMenuItem.separator())
        rightClickMenu.addItem(NSMenuItem(title: "退出", action: #selector(quitApp), keyEquivalent: "q"))
        statusItem.menu = rightClickMenu
        
        // 初始化主窗口(左键点击打开)
        mainWindow = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 300, height: 200),
            styleMask: [.titled, .closable, .miniaturizable],
            backing: .buffered,
            defer: false
        )
        mainWindow.center()
        mainWindow.title = "Main Window"
    }
    
    @objc private func statusBarButtonClicked(_ sender: NSStatusBarButton) {
        guard let event = NSApp.currentEvent else { return }
        if event.type == .leftMouseUp {
            // 左键打开主窗口
            mainWindow.makeKeyAndOrderFront(nil)
            NSApp.activate(ignoringOtherApps: true)
        }
        // 右键自动弹出statusItem.menu,无需额外处理
    }
    
    @objc private func openSettings() {
        // 打开设置窗口
        let settingsWindow = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 250, height: 150),
            styleMask: [.titled, .closable],
            backing: .buffered,
            defer: false
        )
        settingsWindow.center()
        settingsWindow.title = "Settings"
        settingsWindow.makeKeyAndOrderFront(nil)
        NSApp.activate(ignoringOtherApps: true)
    }
    
    @objc private func quitApp() {
        NSApp.terminate(nil)
    }
}

关键说明

  • 通过sendAction(on:)让状态栏按钮响应左右点击事件
  • 在点击回调中区分左键/右键操作:左键打开主窗口,右键自动弹出预设菜单
  • 可根据业务需求自定义窗口内容、菜单选项

内容的提问来源于stack exchange,提问作者B. Mohammad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:54:58