为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
相关产品推荐
相关产品推荐

