NSAnimationContext не анимирует размер кадра для NSButton

С помощью NSAnimationContext.runAnimationGroup(_:_:) как показано в NSAnimationContext документация для анимации как начала, так и размера кадра работает, как ожидается, для некоторых типов представлений (включая NSImageView). Тем не менее, он не работает, как ожидается, для NSButton если я не добавлю явное изменение размера кадра после анимации

Размер кадра анимации дляNSImageView

Следующее работает, как и ожидалось, для NSImageView. Размер перемещен в начало координат и уменьшен до 200x200:

NSAnimationContext.runAnimationGroup({(let context) -> Void in
    context.duration = 2.0
    // Get the animator for an NSImageView
    let a = self.theImage.animator()
    // Move and resize the NSImageView
    a.frame = NSRect(x: 0, y: 0, width: 200, height: 200)
}) {
    print("Animation done")
}

Размер кадра анимации дляNSButton

При выполнении того же самого с NSButton, кнопка будет перемещаться, но не изменяет размер:

NSAnimationContext.runAnimationGroup({(let context) -> Void in
    context.duration = 2.0
    // Get the animator for an NSButton
    let a = self.button.animator()
    // Move and resize the NSImageView
    a.frame = NSRect(x: 0, y: 0, width: 200, height: 200)
}) {
    print("Animation done")
}

Однако, если я добавлю следующую строку кода в конец, после всего кода анимации, он будет работать как положено!

self.button.frame = NSRect(x: 0, y: 0, width: 200, height: 200)

Финальный, рабочий листинг для NSButton является:

NSAnimationContext.runAnimationGroup({(let context) -> Void in
    context.duration = 2.0
    // Get the animator for an NSButton
    let a = self.button.animator()
    // Move and resize the NSImageView
    a.frame = NSRect(x: 0, y: 0, width: 200, height: 200)
}) {
    print("Animation done")
}
self.button.frame = NSRect(x: 0, y: 0, width: 200, height: 200)

Я не смотрю здесь в подарок, но я не понимаю, почему это требуется для NSButton, или даже что заставляет его работать. Может кто-нибудь объяснить, почему явно установить рамку NSButton после анимации код заставляет анимацию работать?

1 ответ

Я подозреваю, что это как-то связано с неявными ограничениями автопоставки, которые генерируются во время выполнения. После изменения фрейма, автоматическая разметка просто возвращает его к исходному размеру.

Я отказался от первоначального подхода в пользу следующего:

  1. Создайте ограничения ширины и / или высоты в Интерфейсном Разработчике. Я использую приоритет по умолчанию 1000 (ограничение обязательно).
  2. Создайте выход для ширины и / или высоты NSLayoutConstraint, Это было сложно в IB: мне пришлось дважды щелкнуть ограничение на вкладке измерений инспектора, после чего был открыт объект ограничения в инспекторе. Затем вы можете выбрать вкладку подключения и подключить розетку.
  3. В моем NSViewController Подкласс Я использую якоря, чтобы определить новую высоту или ширину: theWidthConstraint.constant = 200 с последующим self.view.needsUpdateConstraints = true

Этот подход намного чище и более совместим с системой автоматического размещения. Кроме того, это позволяет легко анимировать все изменения макета, возникающие в результате новой автоматической раскладки:

NSAnimationContext.runAnimationGroup({(let context) -> Void in
    context.duration = 1.0
    self.theWidthConstraint.animator().constant = 200
    // Other constraint modifications can go here
}) {
    print("Animation done")
}
Другие вопросы по тегам