rootViewController 不是您想象的非常具有动画效果的属性。 makeKeyAndVisible 也不是可动画的,您可能应该在运行任何动画之前这样做。
这个 API 本身已经很老了(iOS 4.0),我个人认为它更像是 UIKit 的遗留物,自从 iOS 6 之后翻转视图仍然是一件事时,我还没有看到它被使用过。
iOS 7 中引入的自定义过渡是一种非常舒适的方式来制作任何类型的疯狂动画,但是正如您所注意到的,它创建了一个您并不总是需要的模态层次结构。
所有这些 API 都旨在与容器内的 sibling 视图一起使用。这是文档及其示例中提到的内容。而且 UIWindow 似乎不适合作为全局动画容器。
文档中的示例代码:
[UIView transitionWithView:containerView
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ [fromView removeFromSuperview]; [containerView addSubview:toView]; }
completion:NULL];
我建议您遵循与自定义过渡相同的逻辑,并首先设置虚拟根控制器,它将为您提供动画容器。
然后在其中添加视图或整个视图控制器,并使用
在兄弟视图之间运行动画
+ transitionFromView:toView:duration:options:completion:`
或
- transitionFromViewController:toViewController:duration:options:animations:completion:
或
+ transitionWithView:duration:options:animations:completion:
除此之外,还有一个有用的标志UIViewAnimationOptionShowHideTransitionViews 会自动隐藏翻转的视图以避免它在动画后闪烁或重新出现。
动画结束后,您可以一次调用整个根控制器,用户应该不会注意到这一点。
此 API 也有一些怪癖,例如,如果您在应用程序不在屏幕上时使用它,或者您在当前不可见的窗口上运行它,那么它会简单地吞下调用。我曾经有过类似的支票
if(fromViewController.view.window) {
/* run animations */
} else {
/* swap controllers without animations */
}
我做了一个示例项目来演示如何使用临时容器视图进行过渡
https://github.com/pronebird/FlipRootController
UIWindow 上的示例类别:
@implementation UIWindow (Transitions)
- (void)transitionToRootController:(UIViewController *)newRootController animationOptions:(UIViewAnimationOptions)options {
// get references to controllers
UIViewController *fromVC = self.rootViewController;
UIViewController *toVC = newRootController;
// setup transition view
UIView *transitionView = [[UIView alloc] initWithFrame:self.bounds];
// add subviews into transition view
[transitionView addSubview:toVC.view];
[transitionView addSubview:fromVC.view];
// add transition view into window
[self addSubview:transitionView];
// flush any outstanding animations
// UIButton may cancel transition if this method is called from touchUpInside, etc..
[CATransaction flush];
[UIView transitionFromView:fromVC.view
toView:toVC.view
duration:0.5
options:options
completion:^(BOOL finished) {
// set new root controller after animation
self.rootViewController = toVC;
// move VC's view out of transition view
[self addSubview:toVC.view];
// remove transition view
[transitionView removeFromSuperview];
}];
}
@end