正如@frédéric-blanc 指出的那样:实现这一目标的唯一方法是以编程方式使用NSToolbarItemGroup。
诀窍是将view 和subitems 数组分配给NSToolbarItemGroup。
let group = NSToolbarItemGroup(itemIdentifier: NSToolbarItem.Identifier(rawValue: "NavigationGroupToolbarItem"))
let itemA = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(rawValue: "PrevToolbarItem"))
itemA.label = "Prev"
let itemB = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(rawValue: "NextToolbarItem"))
itemB.label = "Next"
let segmented = NSSegmentedControl(frame: NSRect(x: 0, y: 0, width: 85, height: 40))
segmented.segmentStyle = .texturedRounded
segmented.trackingMode = .momentary
segmented.segmentCount = 2
// Don't set a label: these would appear inside the button
segmented.setImage(NSImage(named: NSImage.goLeftTemplateName)!, forSegment: 0)
segmented.setWidth(40, forSegment: 0)
segmented.setImage(NSImage(named: NSImage.goRightTemplateName)!, forSegment: 1)
segmented.setWidth(40, forSegment: 1)
// `group.label` would overwrite segment labels
group.paletteLabel = "Navigation"
group.subitems = [itemA, itemB]
group.view = segmented
如果您想尝试一下,请查看下面的示例应用代码。
示例应用(针对 Swift 5.1 更新)
这就是您在新的 macOS/Cocoa 示例应用中测试它所需的全部内容:
- 在 Xcode 中,使用默认选项(Swift、storyboards)创建一个新的 macOS 项目。
- 添加一个名为
WindowController.swift 的新文件并将此代码粘贴到其中。
- 在界面生成器中将窗口控制器的类设置为
WindowController。
import Cocoa
class WindowController: NSWindowController, NSToolbarDelegate {
var _toolbar: NSToolbar!
let toolbarItems: [[String: Any]] = [
["title" : "irrelevant :)", "icon": "NSPreferencesGeneral", "identifier": NSToolbarItem.Identifier(rawValue: "NavigationGroupToolbarItem")],
["title" : "Share", "icon": NSImage.shareTemplateName, "identifier": NSToolbarItem.Identifier(rawValue: "ShareToolbarItem")],
["title" : "Add", "icon": NSImage.addTemplateName, "identifier": NSToolbarItem.Identifier(rawValue: "AddToolbarItem")]
]
var toolbarTabsIdentifiers: [NSToolbarItem.Identifier] {
return toolbarItems.compactMap { $0["identifier"] as? NSToolbarItem.Identifier }
}
override func windowDidLoad() {
_toolbar = NSToolbar(identifier: "TheToolbarIdentifier")
_toolbar.allowsUserCustomization = true
_toolbar.delegate = self
window?.toolbar = _toolbar
}
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
guard let infoDictionary: [String : Any] = toolbarItems.filter({ $0["identifier"] as? NSToolbarItem.Identifier == itemIdentifier }).first
else { return nil }
let toolbarItem: NSToolbarItem
if itemIdentifier == NSToolbarItem.Identifier(rawValue: "NavigationGroupToolbarItem") {
let group = NSToolbarItemGroup(itemIdentifier: itemIdentifier)
let itemA = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(rawValue: "PrevToolbarItem"))
itemA.label = "Prev"
let itemB = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(rawValue: "NextToolbarItem"))
itemB.label = "Next"
let segmented = NSSegmentedControl(frame: NSRect(x: 0, y: 0, width: 85, height: 40))
segmented.segmentStyle = .texturedRounded
segmented.trackingMode = .momentary
segmented.segmentCount = 2
// Don't set a label: these would appear inside the button
segmented.setImage(NSImage(named: NSImage.goLeftTemplateName)!, forSegment: 0)
segmented.setWidth(40, forSegment: 0)
segmented.setImage(NSImage(named: NSImage.goRightTemplateName)!, forSegment: 1)
segmented.setWidth(40, forSegment: 1)
// `group.label` would overwrite segment labels
group.paletteLabel = "Navigation"
group.subitems = [itemA, itemB]
group.view = segmented
toolbarItem = group
} else {
toolbarItem = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(rawValue: itemIdentifier.rawValue))
toolbarItem.label = (infoDictionary["title"] as? String)!
let iconImage = NSImage(named: (infoDictionary["icon"] as? String)!)
let button = NSButton(frame: NSRect(x: 0, y: 0, width: 40, height: 40))
button.title = ""
button.image = iconImage
button.bezelStyle = .texturedRounded
toolbarItem.view = button
}
return toolbarItem
}
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return self.toolbarTabsIdentifiers
}
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return self.toolbarDefaultItemIdentifiers(toolbar)
}
func toolbarSelectableItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return self.toolbarDefaultItemIdentifiers(toolbar)
}
func toolbarWillAddItem(_ notification: Notification) {
print("toolbarWillAddItem", (notification.userInfo?["item"] as? NSToolbarItem)?.itemIdentifier ?? "")
}
func toolbarDidRemoveItem(_ notification: Notification) {
print("toolbarDidRemoveItem", (notification.userInfo?["item"] as? NSToolbarItem)?.itemIdentifier ?? "")
}
}