У Finder и Notes есть своеобразное поведение, которое я пытаюсь воспроизвести. «Гибкое пространство» в NSToolbar, по-видимому, учитывает размеры разделенного представления. Например, первая группа кнопок выравнивается с левой стороны с правой стороны боковой панели. Вторая группа значков выравнивается с правой стороны первого столбца. Когда я расширяю боковую панель, элементы панели инструментов перемещаются вместе с ней.Выровнять 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)
}
}
}
Фантастический, это похоже на работу. Два комментария: (1) 'toolbarWillAddItem:' требует немного другого поведения, потому что элементы панели инструментов не обновляются при вызове этого метода. Вместо этого 'setTrackedSplitView:' должен быть вызван непосредственно в этом сетевом элементе. (2) Установка остальных элементов в нуль приводит к неустойчивому поведению и ошибке типа «непризнанный селектор». – Eitot
Вы должны установить только оставшиеся ** предметы с гибким пространством ** для отслеживания 'nil'. Я предполагаю, что под капотом есть определенный подкласс для этих предметов. Вам нужно очистить отслеживаемый вид разделения для них, потому что вы, возможно, предварительно установили его для одного из них, а затем изменили порядок. Что касается '-toolbarWillAddItem:', мой код откладывает обновление элементов до конца цикла цикла запуска с помощью 'dispatch_async()' в основной очереди. –
Вызов его в 'DispatchQueue.main.async()' работает в моем коде только тогда, когда приложение запущено, но при запуске оно, похоже, не работает. Можете ли вы привести пример того, как вы это сделали? – Eitot