一个适用于 macOS 和 Mac Catalyst 的 SwiftUI 风格的声明式 NSToolbar
。
NSToolbar 拥有出色的 API 和难以置信的灵活性,但我发现对于较简单的项目来说,它可能过于冗长,并且由于使用了委托和回调,代码分散在各处,我很难跟踪所有单独的组件。 如果你想在工具栏对象上使用 actions 和 bindings,情况就更是如此,这只会增加每个工具栏所需的代码量。
因此,我发现我并没有将工具栏放入我的(不得不承认是基本的)应用程序中。
我很想看看是否可以生成一个 API,它可以:-
if #available(macOS 11, *)
。此模块不包含 NSToolbar
/NSToolbarDelegate
的全部功能,但提供了核心功能的重要部分。
如果你熟悉 SwiftUI 语法,你会对声明风格感到舒适。
class MyViewController: NSViewController {
// A binder to enable/disable the search field
let searchEnabled = ValueBinder(true)
// The search text binding to the content of the search toolbar item
let searchText = ValueBinder("") { newValue in
Swift.print("Search text is now \(newValue)")
}
...
lazy var customToolbar: DSFToolbar = {
DSFToolbar(
toolbarIdentifier: NSToolbar.Identifier("Core"),
allowsUserCustomization: true
) {
DSFToolbar.Item("item-new")
.label("New")
.isSelectable(true)
.image(ProjectAssets.ImageSet.toolbar_new_document.template)
.willEnable { [weak self] in
self?.canAddDocument() ?? false
}
.action { [weak self] _ in
self?.addDocument()
}
DSFToolbar.Item("item-edit")
.label("Edit")
.isSelectable(true)
.image(ProjectAssets.ImageSet.toolbar_edit_document.template)
.willEnable { [weak self] in
self?.canEditDocument() ?? false
}
.action { [weak self] _ in
self?.editDocument()
}
DSFToolbar.FlexibleSpace()
DSFToolbar.Search("search-field")
.label("Search")
.isSelectable(true)
.bindIsEnabled(searchEnabled)
.bindText(self.searchText)
}
}()
...
// Attaching the window to the toolbar will make the toolbar appear
self.customToolbar.attachedWindow = self.view.window
}
就是这样!
在大多数情况下,你只需要使用 DSFToolbar.Item
、DSFToolbar.Group
和 DSFToolbar.Search
来获得你需要的 90+% 的工具栏功能。
如果你的目标是 10.15 或更高版本,则通过在 group 上设置 isBordered(true)
,你可以将 DSFToolbar.Group
用作分段样式控件。
通过在工具栏的构造函数中设置 allowsUserCustomization: true
,可以将工具栏标记为可自定义。
此外,你可以通过调用 displayMode()
或使用 bindDisplayMode()
在你的 DSFToolbar
实例上进行绑定,来设置或绑定到工具栏的显示模式(例如,.iconAndLabel
,.labelOnly
)。
可以使用 isDefault
标记工具栏项目,以指示该项目应显示在默认工具栏上。 标记为 isDefault(false)
的项目最初不会出现在工具栏中,但会出现在自定义调色板中,以便可以添加。
标记为 isSelectable
的工具栏项目将在按下时显示选择标记。 你可以通过为 onSelectionChange
属性提供 block 来检测工具栏选择更改。
self.customToolbar = DSFToolbar(NSToolbar.Identifier("My Toolbar")) {
...
}
.onSelectionChange { newToolbarSelection in
// Do something when the selection changes
}
提供回调(例如,对单击的响应)的项目可以提供 block action 作为声明的一部分进行响应。
self.customToolbar = DSFToolbar(NSToolbar.Identifier("Buttons")) {
DSFToolbar.Image(NSToolbarItem.Identifier("toolbar-image-bordered"))
.label("Burger")
.action { _ in
Swift.print("Clicked burger!")
}
}
在任何 block 中捕获 self
都会创建 retain cycles,因此如果需要在 block 中捕获 self,请确保使用 [weak self]
。
某些工具栏项目可以请求信息。 例如,你可以在声明期间传递一个 block,该 block 提供 Image
项目的启用状态。
在任何 block 中捕获 self
都会创建 retain cycles,因此如果需要在 block 中捕获 self,请确保使用 [weak self]
。
self.customToolbar = DSFToolbar(NSToolbar.Identifier("Enabled-buttons")) {
DSFToolbar.Image(NSToolbarItem.Identifier("toolbar-image-bordered"))
.label("Burger")
.willEnable { [weak self] in
return self?.IsBurgerMenuEnabled() ?? false
}
.action { _ in
Swift.print("Clicked burger!")
}
}
可以通过 bindings 挂钩许多功能,以便在工具栏项目之间传递信息。 例如,你可以将搜索项的内容挂钩到类变量,以观察搜索字段的内容何时更改。
此库使用 DSFValueBinders 在本地属性和工具栏项目之间提供双向 bindings。
let searchText = ValueBinder("") {
// Update the search with the new string
}
...
self.customToolbar = DSFToolbar("Search") {
DSFToolbar.Search("toolbar-search-field")
.label("Search")
.bindSearchText(self.searchText)
}
完成工具栏后,需要在工具栏对象上调用 close()
。 这将删除在创建工具栏期间设置的任何 bindings 或 observers 或自定义控件。
self.customToolbar.close()
类型 | 描述 |
---|---|
核心 | 所有工具栏项目类型可用的核心元素 |
类型 | 可用 | 描述 |
---|---|---|
Item | macOS macCatalyst |
基本工具栏“图像”类型。 提供基本图像、标签、action 等。 大多数时候,你都需要这个。 |
Group | macOS macCatalyst |
将多个项目组合在一起以表示一个公共单元。 通过在 group 上设置 isBordered(true) ,这也可以用作分段控件样式(在 catalyst 和 10.15 中)。 |
Search | macOS macCatalyst |
提供一个搜索文本字段 |
Segmented | macOS macCatalyst |
一个简单的分段控件 |
Separator | macOS11+ macCatalyst |
挂钩到 NSSplitView 以将工具栏分隔符跟踪到拆分视图分隔符 |
Button | macOS | 包含 NSButton 的工具栏项目 |
PopupButton | macOS | 激活时显示菜单的工具栏项目 |
PopoverButton | macOS | 激活时显示 popover 的工具栏项目 |
PopupMenu | macOS | 显示可选择菜单项的工具栏项目 |
View | macOS | 包含自定义视图的工具栏项目 |
你可以在 Demos
文件夹下找到预制演示
DSFToolbar Demo
:适用于 Xcode 12 的项目,包含 macOS 和 macCatalyst 的目标MIT。 随意使用! 如果你在某个地方使用了它,请告诉我,我很乐意听到这件事。
MIT License
Copyright (c) 2024 Darren Ford
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.