似乎有好久都没有更新博客了(´・_・`),十一回家的火车上看了苹果最近更新的View Controller Programming Guide,回来后忙里偷闲试验了自定义view controller之间的转场动画,就写这篇博客来记录一下吧。
iOS系统本身为一个UIViewController
对象提供了这样几种转场动画形式(UIModalTransitionStyle
),分别是:
UIModalTransitionStyleCoverVertical(默认,自下而上覆盖)
UIModalTransitionStyleFlipHorizontal(水平翻转)
UIModalTransitionStyleCrossDissolve(溶解)
UIModalTransitionStylePartialCurl(翻页)
以前,我一直以为view controller之间的转场动画是一种神奇的存在,是因为我没有意识到UITransitionView
的存在。
先写一个特别简单的demo,就是在rootViewController上present一个UIViewController
的对象,比如这样:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = [UIColor redColor];
[self presentViewController:viewController animated:YES completion:nil];
}
运行app,等上层的view controller弹出,用Xcode的视图调试工具,能看到这样的视图结构:
其中的那个UIView
,就是presentedViewController
的视图,可以发现,它是一个UITransitionView
对象的子视图。这个UITransitionView
对象,就是view controller之间转场动画的画布。
自定义view controller间的转场动画
iOS7及之后版本中,第三方程序员可以为自己的app设置自定义的view controller转场动画了。
如果想要自定义view controller之间的转场动画,首先要给即将展现的那个view controller设置transitionDelegate
。
这个transitionDelegate
所对应的类需要实现UIViewControllerTransitioningDelegate
协议。如果只是想要自定义转场动画,而不需要让用户与这个动画有所交互的话,可以只用实现协议中的这两个方法:
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
和
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;
其中,返回的对象所属的类需要实现UIViewControllerAnimatedTransitioning
协议。这个类如何实现,是自定义动画的关键。
比如我定义了一个名叫XSQAnimationObject
的类,它实现了UIViewControllerAnimatedTransitioning
协议。然后将它的实例对象作为上两个方法(present和dismiss)的返回值。
在XSQAnimationObject
中,必须实现UIViewControllerAnimatedTransitioning
协议中的这两个方法:
//在这个方法的实现中,返回转场动画的时长
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
和
//在这个方法的实现中,进行转场动画
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
其中的transitionContext
这个参数,可以提供与对转场动画必要的信息,比如presenting view controller,presented view controller等。transitionContext
中的containerView
,便是应该呈现转场动画的视图。如果在运行时打印出来,会发现这个containerView
是UITransitionView
的实例,其实也是最开始图上的那个UITransitionView
。
在转场动画完成后,一定要记得调用transitionContext
的
completeTransition:
方法。只有这样,presentViewController:animated:completion:
中的completion块才能被调用。
最后,自己写了一个简单的demo,尝试了“zoom”效果的转场动画,虽然这个效果已经满大街都是了,但还是放上我写的代码的github链接吧(⊙ω⊙)
参考
View Controller Programming Guide: Customizing the Transition Animations
自定义 ViewController 容器转场