最近开发了JustTodo和DeskNote两个macOS应用,都是启动入口在菜单栏的,通过菜单栏上图标点击,快速执行相关操作,这让我想起我开发第一款菜单栏app Translator时的痛苦。因为想使用最新的SwiftUI作为UI框架,但是此框架构建菜单栏app的资料很少,大多数都是生成一个简单菜单,而不是可以自定义的复杂界面,尤其是用swiftUI构建的界面。
为了解决这一痛点,在总结了JustTodo和DeskNote两个macOS应用开发经验后,决心自己做了一个菜单栏应用快捷库Tray,方便以后使用。
一、引入
在macOS项目中,点击File -> Add Package Dependencies …,在包管理窗口的搜索框中,复制粘贴https://github.com/boybeak/Tray.git
,待检索到库信息,点击Add Package按钮。
二、使用
以SwiftUI应用为例,在代码入口处,声明一个AppDelegate
.
2.1 初始化
1 | @main |
这里body中的
Settings {}
代码,是为了隐藏启动时的主窗口。
然后创建AppDelegate类。
1 | class AppDelegate: NSObject, NSApplicationDelegate { |
引入相关的类Tray并声明我们的托盘管理对象var tray: Tray
,并在applicationDidFinishLaunching
中为改对象赋值,传入资源文件名称,或者使用SF Symbols
也可以,只是参数名要改为systemSymbolName,如果有更多要求,也可以直接以icon为参数名,传入一个NSImage对象。
然后在闭包中配置tray.
2.2 配置托盘信息
1 | func configTray(tray: Tray) { |
这里设置的是一个SwiftUI的View,你也可以设置NSView或者NSViewController,除了界面参数,还有其他三个可选参数:
- behavior: NSPopover的behavior,默认值为.transient,即点击窗口以外区域隐藏弹出界面;
- level: NSPopover的窗口层级,默认为.floating;
- size: NSPopover的大小,默认为nil,即使用View自己配置的大小;
在JustTodo应用中,其效果如下图:
到这里,主要的配置就完成了,如果你不想弹出一个NSPopover,你也可以接管托盘图标的左键事件。
1 | tray.setOnLeftClick { |
返回true,表示事件完全处理,会阻止默认行为。默认行为就是弹出NSPopover,前提是设置了view。比如在DeskNote中,我接管了此事件,改为弹出笔记的编辑页面。
当然,同样你也可以为右键增加事件。
1 | tray.setOnRightClick { |
返回true,表示事件完成处理,阻止默认行为。默认行为是弹出菜单,前提是设置了菜单,正如下边代码。
1 | let menu = NSMenu() |
效果如下:
这就是一些基本的使用和配置步骤。接下来是一些相关的小建议。
三、建议
3.1 托盘图标尺寸
1x: 1818
2x: 3636
3x: 54*54
3.2 隐藏Docker栏中应用的图标
在Info.plist中,增加一个配置项: Application is agent(UIElement) - YES.
Author: boybeak