NSStatusItem
NSWindow
(当使用 .window
样式时)MenuBarExtra
menu
和 window
的样式(参见 已知问题)没有第一方 MenuBarExtra API 来获取或设置菜单的显示状态、访问状态栏项目或访问弹出窗口的 NSWindow。(截至 Xcode 16.1 仍然如此)
.menuBarExtraAccess(isPresented:) { statusItem in }
场景修饰符,具有NSStatusItem
.introspectMenuBarExtraWindow { window in }
视图修饰符,传入 NSWindow
引用该库以 Swift Package Manager (SPM) 包的形式提供。
在将库添加到项目或 Swift 包时,请使用 URL https://github.com/orchetect/MenuBarExtraAccess
。
然后导入库
import SwiftUI
import MenuBarExtraAccess
通过单击窗口中的按钮显示菜单额外菜单的示例
@main struct MyApp: App {
@State var isMenuPresented: Bool = false
var body: some Scene {
WindowGroup {
Button("Show Menu") { isMenuPresented = true }
}
MenuBarExtra("MyApp Menu", systemImage: "folder") {
Button("Menu Item 1") { print("Menu Item 1") }
Button("Menu Item 2") { print("Menu Item 2") }
}
.menuBarExtraStyle(.menu)
.menuBarExtraAccess(isPresented: $isMenuPresented) { statusItem in // <-- the magic ✨
// access status item or store it in a @State var
}
}
}
弹出窗口中的按钮关闭弹出窗口并执行操作的示例
@main struct MyApp: App {
@State var isMenuPresented: Bool = false
var body: some Scene {
MenuBarExtra("MyApp Menu", systemImage: "folder") {
MyMenu(isMenuPresented: $isMenuPresented)
.introspectMenuBarExtraWindow { window in // <-- the magic ✨
window.animationBehavior = .alertPanel
}
}
.menuBarExtraStyle(.window)
.menuBarExtraAccess(isPresented: $isMenuPresented) { statusItem in // <-- the magic ✨
// access status item or store it in a @State var
}
}
}
struct MyMenu: View {
@Binding var isMenuPresented: Bool
var body: some View {
Button("Perform Action") {
isMenuPresented = false
performSomeAction()
}
}
}
MenuBarExtraAccess 完全兼容应用程序中的一个或多个 MenuBarExtra。
只需向 .menuBarExtraAccess()
和 .introspectMenuBarExtraWindow()
添加一个索引号参数,该参数反映 MenuBarExtra
声明的顺序。
var body: some Scene {
MenuBarExtra("MyApp Menu A", systemImage: "folder") {
MyMenu(isMenuPresented: $isMenuPresented)
.introspectMenuBarExtraWindow(index: 0) { window in // <-- add index 0
// ...
}
}
.menuBarExtraStyle(.window)
.menuBarExtraAccess(index: 0, isPresented: $isMenuPresented) // <-- add index 0
MenuBarExtra("MyApp Menu B", systemImage: "folder") {
MyMenu(isMenuPresented: $isMenuPresented)
.introspectMenuBarExtraWindow(index: 1) { window in // <-- add index 1
// ...
}
}
.menuBarExtraStyle(.window)
.menuBarExtraAccess(index: 1, isPresented: $isMenuPresented) // <-- add index 1
}
希望 Apple 在未来版本的 SwiftUI 中实现这些功能(以及更多)的原生版本!
在此之前,已提交雷达作为功能请求:FB11984872
查看 MacControlCenterUI,这是一个基于 MenuBarExtraAccess 构建的 SwiftUI 包,用于轻松构建控制中心风格的菜单。
.menuBarExtraStyle(.menu)
时,SwiftUI 会导致弹出菜单在菜单打开时阻止运行循环,这意味着isPresented
绑定将无法按预期工作。isPresented
绑定设置为 false
无效。由一群穿着风衣并自称 @orchetect 的 🐹 仓鼠编写。
在 MIT 许可证下获得许可。 有关详细信息,请参阅 LICENSE。
如果您喜欢使用 MenuBarExtraAccess 并希望在经济上为开源做出贡献,GitHub 赞助将不胜感激。 也欢迎反馈和代码贡献。
欢迎贡献。 鼓励在新提交功能或修改的 PR 之前,先在 Discussions 中发帖。