通过 SwiftUI 的 MenuBarEtra 实现菜单栏小工具
在 macOS 下有许多优秀的状态栏小工具,如果你想开发自己的状态栏小工具,看我这篇文章应该会对你有所帮助!很早之前写过一篇使用 AppKit 实现的文章,而今天,我们完全通过 SwiftUI 的 MenuBarExtra 快速实现,适用于 macOS 13+ 版本!
若使用 Appkit 的实现方式请参考:macOS 开发之菜单栏形式的状态栏小工具。
实现纯状态栏小工具,包含以下操作:
- 添加 MenuBarExtra 实现状态栏小工具;
- 删除主窗口;
- 实现 Dock 栏上不显示应用图标。
如果只是在已开发应用增加状态栏的操作入口,可忽略第二、三步!
平台
- macOS 13.5.2
- Xcode 15.0
- swift 5.9
本文使用上述平台实现,版本不同可能有些差异,但基本思路一致。
新建工程
我们先新建一个工程,当然也可以在自己已有工程中添加实现,注意要将应用的 Deplyment Target 设置到 13.0
以上。
New Project -> macOS -> App,点击 Next,我这里 Product Name 设置为 MenuBarAppDemo
,Language 选择 Swift
,Interface 选择 SwiftUI,最后选择保存目录点击创建 Create 。
记得要配置一下 Project 和 Target 的 Deployment Target 版本。
MenuBarExtra 支持 macOS 13.0+
,我这里就选 13.0
了。
添加 MenuBarExtra
打开 App 文件 MenuBarAppDemoApp.swift,在 WindowsGroup
下面添加合适的 MenuBarExtra
即可。
有八种方式,按照自己的需求选择就好,我这里选择使用 SF Symbol 图像作为图标的接口 MenuBarExtra(content:label:)
。
- 点击图标显示的内容为 ContentView.swift 中定义的内容;
- 自定义状态栏显示的内容,这里添加了 Image 和 Text;
menuBarExtraStyle
选择了window
。- .menu: 将内容渲染为从菜单栏图标下拉的菜单,如下形式:
- .window: 将内容渲染在一个类似于弹出窗口的窗口中,如下形式:
⌘
+r
运行应用程序,可以看到状态栏出现了泰迪熊的图标和 Teddy ,点击也能看到显示 ContentView 的内容,我们就可以通过修改 ContentView.swift 自定义内容了,比如:
- 修改为
Text("hello, Teddy!")
; - 添加一个退出应用的按钮,并绑定了
⌘
+q
的快捷键。
🎉再次⌘
+r
运行,菜单栏是这样的:
🤔如果修改 menuBarExtraStyle
为 .menu
,则会按照菜单形式渲染内容:
🖌️.menuBarExtraStyle
为.menu
时某些控件可能会失效😂,只能显示内容(按照菜单项高度、图像以 template 方式渲染)无法交互🤯,比如 Stepper、Slider 等,像基本的 Button、Text、Divider、Image 等还是能正常显示的。
💡如果你想完全不受限制的定制自己希望显示的内容还是选.window
吧!
实现Dock 栏不显示应用图标
导航栏选择 MenuBarAppDemo,Targets 选择 MenuBarAppDemo,找到 Info 下的 Custom macOS Application Target Properties,添加一项 Application is agent (UIElement) 并设置值为 YES
。
⌘
+r
运行应用程序,正常的话在 Dock 栏就看不到应用程序的图标了。
删除主窗口
直接删除 MenuBarAppDemoApp.swift 中的 windowGroup
内容就好了,最终代码如下:
⌘
+r
运行应用程序,正常的话应用的主窗口也没有了。
🎉 至此,纯菜单栏小工具的架子也就搭好了,后面根据自己的需要调整 ContentView 内容就好啦,是不是很简单🚀!
附件
本文 Demo 代码: MenuBarAppDemo。
总结
本文的方式是纯 SwiftUI 的实现方式,受到系统版本的限制,大家根据自己的 App 的情况酌情选择方案!除了macOS 开发之菜单栏形式的状态栏小工具讲中使用 Appkit 方式之外,也有 SwiftUI + Appkit 的方式(如下代码),不管用什么方式自己用着顺手、满足功能和开发需求就好,不必过于纠结!我个人更倾向于纯 SwiftUI 的方式(因为这是 Apple 发力的方向,路久但可期🔥),相信你也会有自己明确的选择!