初始注释
事实证明这很棘手,因为需要考虑很多事情:
因此,简单地使用拆分视图或布局指南约束特定工具栏项不是一种选择(因为该项目可能位于与预期不同的位置或根本不存在)。
经过数小时的“黑客攻击”,我终于找到了一种可靠的方法来实现不使用任何内部/未记录方法的所需行为。这是它的外观:
如何
而不是标准NSToolbarFlexibleSpaceItem
创建NSToolbarItem
一个自定义视图。这将作为您灵活的、调整大小的空间。您可以在代码或 Interface Builder 中执行此操作:
为您的工具栏和灵活空间(在各自的内部NSWindowController
)创建插座/属性:
@IBOutlet weak var toolbar: NSToolbar!
@IBOutlet weak var tabSpace: NSToolbarItem!
在同一个窗口控制器中创建一个方法来调整空间宽度:
private func adjustTabSpaceWidth() {
for item in toolbar.items {
if item == tabSpace {
guard
let origin = item.view?.frame.origin,
let originInWindowCoordinates = item.view?.convert(origin, to: nil),
let leftPane = splitViewController?.splitViewItems.first?.viewController.view
else {
return
}
let leftPaneWidth = leftPane.frame.size.width
let tabWidth = max(leftPaneWidth - originInWindowCoordinates.x, MainWindowController.minTabSpaceWidth)
item.set(width: tabWidth)
}
}
}
set(width:)
在扩展中定义方法NSToolbarItem
如下:
private extension NSToolbarItem {
func set(width: CGFloat) {
minSize = .init(width: width, height: minSize.height)
maxSize = .init(width: width, height: maxSize.height)
}
}
使您的窗口控制器符合NSSplitViewDelegate
并将其分配给您的拆分视图的delegate
属性。1NSSplitViewDelegate
在您的窗口控制器中实现以下协议方法:
override func splitViewDidResizeSubviews(_ notification: Notification) {
adjustTabSpaceWidth()
}
这将产生所需的调整大小行为。(用户仍然可以完全删除空间或重新定位它,但他总是可以将其添加回前面。)
1 注意:
如果您使用的是NSSplitViewController
,系统会自动将该控制器分配给其拆分视图的delegate
属性,您无法更改它。因此,您需要子类化NSSplitViewController
、覆盖其splitViewDidResizeSubviews()
方法并从那里通知窗口控制器。您可以使用以下代码来实现:
protocol SplitViewControllerDelegate: class {
func splitViewControllerDidResize(_ splitViewController: SplitViewController)
}
class SplitViewController: NSSplitViewController {
weak var delegate: SplitViewControllerDelegate?
override func splitViewDidResizeSubviews(_ notification: Notification) {
delegate?.splitViewControllerDidResize(self)
}
}
不要忘记将您的窗口控制器分配为拆分视图控制器的委托:
override func windowDidLoad() {
super.windowDidLoad()
splitViewController?.delegate = self
}
并实现各自的委托方法:
extension MainWindowController: SplitViewControllerDelegate {
func splitViewControllerDidResize(_ splitViewController: SplitViewController) {
adjustTabSpaceWidth()
}
}