Анимация изменений в contentViewController NSPopover

У меня есть NSPopover, который переключается между двумя контроллерами представления.

Я установил один при запуске,

self.popover.contentViewController = viewController1;

и я перехожу на другой в зависимости от действия пользователя:

self.popover.contentViewController = viewController2;

AppKit делает некоторые анимации для самого NSPopover, чтобы приспособить второй VC, которые работают хорошо, но переход между двумя представлениями View Controller вызывает раздражение. Я бы хотел, чтобы они входили и выходили горизонтально или, по крайней мере, пересекались.

Я использую представления с поддержкой слоев, которые я устанавливаю следующим образом в методе AppDelegate applicationDidFinishLaunching:

self.popover.contentViewController.view.wantsLayer = YES;
self.popover.contentViewController.view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;

Вот что я пробовал:

  • затухание представления первого контроллера представления в -viewWillDisappear и затухание представления второго контроллера представления в -viewWillAppear. Это немедленно затухает вид первого VC и не возвращает вид второго VC обратно.
  • затухание слоя представления первого VC перед переключением всплывающего окна contentViewController:

    CALayer *theLayer = self.popover.contentViewController.view.layer;
    
    CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fadeAnim.fromValue = [NSNumber numberWithFloat:1.0];
    fadeAnim.toValue = [NSNumber numberWithFloat:0.0];
    fadeAnim.duration = 1.0;
    [theLayer addAnimation:fadeAnim forKey:@"opacity"];
    
    theLayer.opacity = 0.0;
    
    self.popover.contentViewController = self.viewController;
    

Эта вторая стратегия не ждет завершения анимации перед переключением контроллеров представления.

Как анимировать изменение contentViewController NSPopover?


person magiclantern    schedule 08.07.2015    source источник


Ответы (1)


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

toController.view.frame = fromController.view.bounds;                           
[containerViewController addChildViewController:toController];                                     
[fromController willMoveToParentViewController:nil];

[containerViewController transitionFromViewController:fromViewController
                                     toViewController:toViewController
                                             duration:0.2
                                              options:UIViewAnimationOptionTransitionCrossDissolve
                                           animations:nil
                                           completion:^(BOOL finished) {
                                               [fromViewController removeFromParentViewController];
                                               [toViewController didMoveToParentViewController:containerViewController];
                                               toViewController.view.frame = containerViewController.view.bounds;
                                           }];

Где containerViewController — это ваш contentViewController.

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

Дополнительная информация от Apple здесь: https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html

И хорошее руководство по пользовательским переходам здесь: http://www.objc.io/issues/12-animations/custom-container-view-controller-transitions/

person Max    schedule 08.07.2015
comment
Спасибо, Макс. Этот вопрос касается Cocoa (Mac), а не Cocoa touch (iOS), поэтому, хотя методы похожи, они не одинаковы. В итоге я использовал эквивалент предложенного вами метода. - person magiclantern; 08.07.2015
comment
Я также должен отметить, что я не мог сделать это напрямую с contentViewController NSPopover, мне пришлось добавить фиктивный пустой контроллер представления, чтобы он действовал как родитель моих двух VC, и назначить contentViewController NSPopover этому родительскому контроллеру представления. - person magiclantern; 08.07.2015