Как выровнять панель инструментов (или ее элементы) по переднему краю дочернего элемента контроллера представления разделения? - PullRequest
0 голосов
/ 01 марта 2019

В iOS панель инструментов может быть добавлена ​​к любому представлению.Однако в macOS кажется возможным только добавить панель инструментов в окно.

Я работаю над приложением с контроллером разделенного вида с панелью инструментов, но элементы панели инструментов имеют значение только в отношениик контексту контроллера правого представления .

Например, скажем, у меня есть какой-то текстовый редактор, где на левой панели отображаются все документы (как в приложении Notes), а на правой панели отображается фактический тексткоторый можно редактировать.Кнопки форматирования влияют только на текст в правой панели.Таким образом, кажется очень интуитивно понятным поместить панель инструментов в эту правую панель вместо того, чтобы растягивать ее по всей ширине окна.

Example window with split view controller

Есть ли способ достичь этого? (Или есть хорошая причина UX, почему это было бы плохой практикой?)

Я заметил, как Apple решила эту проблему с точки зрения UX в своем приложении Notes: они все еще используют панель инструментов полной ширины, новыровняйте элементы кнопок, которые относятся только к правой панели, с передним краем этой панели.

Notes App Screenshot

Таким образом, в этом случае невозможноразместить панель инструментов в контроллере вида, как я могу выровнять элементы панели инструментов по переднему краю правого контроллера вида , как показано на скриншоте выше?


Редактировать:

Согласно ответу TimTwoToes и сообщениям, связанным Willeke в комментариях, представляется возможным использоватьАвтоматическая разметка для ограничения элемента панели инструментов дочерним представлением разделенного представления.Это решение будет работать, если бы была фиксированная раскладка панели инструментов.Однако Apple рекомендует (по уважительной причине) разрешить пользователям настраивать панель инструментов вашего приложения.

Таким образом, я не могу добавить ограничения для фиксированного элемента на панели инструментов.Вместо этого жизнеспособным решением, по-видимому, является использование ведущего гибкого пространства и соответствующая его размер.

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Исходные примечания

Оказывается, это сложно, потому что есть много вещей, которые необходимо учитывать:

  • Авто макет не работает должным образом сэлементы панели инструментов.(Я прочитал несколько постов, в которых упоминается, что Apple классифицирует это как ошибку.)

  • Обычно пользователь может настроить панель инструментов вашего приложения (добавлять и удалять элементы).Мы не должны лишать пользователя этой опции.

Таким образом, просто ограничить конкретный элемент панели инструментов разделенным представлением или руководством по макету не вариант (поскольку элемент может находиться надругое положение, чем ожидалось, или его нет вообще).

После нескольких часов "взлома" я наконец нашел надежный способ достичь желаемого поведения, который не использует никаких внутренних / недокументированных методов.Вот как это выглядит:

Example animation of resizing flexible view


How To

  1. Вместо стандартного NSToolbarFlexibleSpaceItemсоздайте NSToolbarItem с пользовательским представлением.Это будет вашим гибким, изменяющим размер пространством.Вы можете сделать это в коде или в Интерфейсном Разработчике:

    Toolbar customization in Interface Builder

  2. Создание точек / свойств для панели инструментов и вашего гибкого пространства (внутри соответствующего NSWindowController):

    @IBOutlet weak var toolbar: NSToolbar!
    @IBOutlet weak var tabSpace: NSToolbarItem!
    
  3. Создайте метод внутри того же контроллера окна, который регулирует ширину пространства:

    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)
            }
        }
    

    }

  4. Определите метод set(width:) в расширении для NSToolbarItem следующим образом:

    private extension NSToolbarItem {
    
        func set(width: CGFloat) {
            minSize = .init(width: width, height: minSize.height)
            maxSize = .init(width: width, height: maxSize.height)
        }
    
    }
    
  5. Настройте контроллер окна на NSSplitViewDelegate иприсвойте его свойству delegate вашего разделенного представления. 1 Реализуйте следующий NSSplitViewDelegate метод протокола в вашем контроллере окна:

    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()
    }

}
0 голосов
/ 01 марта 2019

Нет собственного способа создания «локальной» панели инструментов.Вам придется создать элемент управления самостоятельно, но я считаю, что это будет просто сделать.

Выравнивание элементов панели инструментов с помощью autolayout описано здесь .Совместите с пользовательским элементом панели инструментов, описанным Мишей.

Способ macOS - использовать решение панели инструментов и сделать их контекстно-зависимыми.В этом случае кнопки текстового атрибута включаются, когда правая панель имеет фокус, и отключаются, когда она теряет фокус.

...