Анимация изменений Auto Layout одновременно с изменением размера содержимого NSPopover

Я пытаюсь воспроизвести поведение навигационных представлений iTunes 11 во всплывающем окне. Однако я не могу найти способ, чтобы моя анимация происходила одновременно с изменением всплывающего окна contentSize.

Базовая установка, которую я имею, — это подкласс пользовательского представления MyPopoverNavigationView с двумя подпредставлениями: старым и новым представлениями, между которыми я хочу, чтобы всплывающее окно перемещалось. contentViewController всплывающего окна имеет экземпляр MyPopoverNavigationView в качестве view. Я сделаю это:

// Configure constraints how I want them to show the new popover view
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *ctx) {
    [ctx setDuration:0.25];
    [ctx setAllowsImplicitAnimation:YES];
    [self layoutSubtreeIfNeeded];
} completionHandler:nil];

Насколько я могу судить из видеороликов Auto Layout WWDC 2012, это рекомендуемый способ анимации изменений кадров представлений в результате изменений ограничений. Это работает, но анимация происходит в два этапа:

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

Судя по установке некоторых точек останова, похоже, что -layoutSubtreeIfNeeded в конечном итоге вызывает частный метод всплывающего окна с именем _fromConstraintsSetWindowFrame:, который выполняет анимацию размера всплывающего окна вне моей группы анимации. Продолжительность моего контекста не соблюдается, и мои анимации не происходят до тех пор, пока не будет завершено изменение размера всплывающего окна.

Как я могу заставить свои представления анимироваться вместе с изменением размера всплывающего окна?


person Tim    schedule 09.02.2013    source источник


Ответы (2)


Оказывается, хитрость заключается в том, чтобы явно установить свойство contentSize всплывающего окна за пределами блоков анимации и завершения. Соответствующий фрагмент из образца проекта GitHub, который я собрал, чтобы разобраться, выглядит так:

// Configure constraints for post-navigation view layout
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *ctx) {
    [ctx setDuration:0.25];
    [ctx setAllowsImplicitAnimation:YES];
    [self layoutSubtreeIfNeeded];
} completionHandler:^{
    // Tear down some leftover constraints from before the transition
}];

// Explicitly set popover's contentSize so its animation happens simultaneously
containingPopover.contentSize = postTransitionView.frame.size;
person Tim    schedule 14.02.2013

Это отлично работает для меня в Sierra:

let deltaHeight = 8 
let contentSize = popover.contentSize  
NSAnimationContext.runAnimationGroup({ (context) -> Void in
    context.allowsImplicitAnimation = true
    popover.contentSize = NSSize(width: contentSize.width, height: contentSize.height+deltaHeight)
})
person Daniel    schedule 26.10.2017