cocoa – 将NSToolbarItems与NSSplitView列对齐

Finder和Notes有一种奇特的行为,我正在寻求重现. NSToolbar中的“灵活空间”似乎考虑了拆分视图的尺寸.例如,第一组按钮在左侧与侧栏的右侧对齐.第二组图标与第一列的右侧对齐.当我扩展侧边栏时,工具栏项随之移动.

有可能重现这个吗?

《cocoa – 将NSToolbarItems与NSSplitView列对齐》

使用@KenThomases提供的解决方案,我已经实现了如下:

final class MainWindowController: NSWindowController {
    override func windowDidLoad() {
        super.windowDidLoad()
        window?.toolbar?.delegate = self
        // Make sure that tracking is enabled when the toolbar is completed
        DispatchQueue.main.async {
            self.trackSplitViewForFirstFlexibleToolbarItem()
        }
    }
}

extension MainWindowController: NSToolbarDelegate {
    func toolbarWillAddItem(_ notification: Notification) {
        // Make sure that tracking is evaluated only after the item was added
        DispatchQueue.main.async {
            self.trackSplitViewForFirstFlexibleToolbarItem()
        }
    }

    func toolbarDidRemoveItem(_ notification: Notification) {
        trackSplitViewForFirstFlexibleToolbarItem()
    }

    /// - Warning: This is a private Apple method and may break in the future.
    func toolbarDidReorderItem(_ notification: Notification) {
        trackSplitViewForFirstFlexibleToolbarItem()
    }

    /// - Warning: This method uses private Apple methods that may break in the future.
    fileprivate func trackSplitViewForFirstFlexibleToolbarItem() {
        guard var toolbarItems = self.window?.toolbar?.items, let splitView = (contentViewController as? NSSplitViewController)?.splitView else {
            return
        }

        // Add tracking to the first flexible space and remove it from the group
        if let firstFlexibleToolbarItem = toolbarItems.first, firstFlexibleToolbarItem.itemIdentifier == NSToolbarFlexibleSpaceItemIdentifier {
            _ = firstFlexibleToolbarItem.perform(Selector(("setTrackedSplitView:")), with: splitView)
            toolbarItems.removeFirst()
        }

        // Remove tracking from other flexible spaces
        for flexibleToolbarItem in toolbarItems.filter({ $0.itemIdentifier == NSToolbarFlexibleSpaceItemIdentifier }) {
            _ = flexibleToolbarItem.perform(Selector(("setTrackedSplitView:")), with: nil)
        }
    }
}

最佳答案 您可以使用Apple-private方法执行此操作,但App Store中不允许这样做.

在NSToolbarItem上有一个私有方法-setTrackedSplitView:.它需要一个NSSplitView *作为参数.您需要在要跟踪拆分视图的灵活空间工具栏项上调用它,并将它应该跟踪的拆分视图传递给它.为了防止Apple移除该方法,您应该在尝试使用它之前检查NSToolbarItem是否响应该方法.

由于用户可以自定义和重新排序工具栏,因此通常需要枚举窗口工具栏的项目.对于标识符为NSToolbarFlexibleSpaceItemIdentifier的第一个,您可以设置它应跟踪的拆分视图.对于所有其他灵活空间项目,清除(设置为nil)要跟踪的拆分视图.您需要在首次设置窗口时再次在工具栏委托的-toolbarWillAddItem:和-toolbarDidRemoveItem:方法中执行此操作.还有另一个未记录的委托方法-toolbarDidReorderItem:,我发现更新工具栏很有用.

点赞