深入学习iOS7自定义导航转场动画

2020-01-14 20:05:04刘景俊

• pushViewController
• popViewController
• setViewControllers 

在示例应用程序中,我创建了一系列转场动画,在动画中使用了之前讲解过的新引入的弹簧动画和关键帧block方法,现在让我们来看看如何使用新API来自定义上述的转场动画。
1、核心概念:动画控制器
那么,如何在使用自定义动画的同时不影响视图的其他属性?对此苹果公司提供了一个新的协议:UIViewControllerAnimatedTransitioning,我们可以在协议方法中编写自定义的动画代码。苹果开发者文档中称实现了此协议的对象为动画控制器。 
由于我们使用了协议这一语法特性,自定义动画的代码可以灵活的放在自己想要的位置。你可以创建一个专门用于管理动画的类, 也可以让UIViewController实现UIViewControllerAnimatedTransitioning接口。由于需要实现一系列不同的动画,因此选择为每个动画创建一个类。接下来创建这些动画类的通用父类——BaseAnimation,它定义了一些通用的属性和助手方法。
让我们来看第一个动画,使用UINavigationController推入推出视图时,会有一个简单的缩放效果。


-(void)animateTransition: 
(id)transitionContext { 
//获取容器视图引用 
UIView *containerView = [transitionContext 
containerView]; 
UIViewController *fromViewController = [transitionContext 
viewControllerForKey:UITransitionContextFromViewControllerKey 
]; 
UIViewController *toViewController = [transitionContext 
viewControllerForKey:UITransitionContextToViewControllerKey]; 
if (self.type == AnimationTypePresent) { 
//插入“to”视图,初始缩放值为0.0 
toViewController.view.transform = 
CGAffineTransformMakeScale(0.0, 0.0); 
[containerView insertSubview:toViewController.view 
aboveSubview:fromViewController.view]; 
//缩放“to”视图为想要的效果 
[UIView animateWithDuration:[self 
transitionDuration:transitionContext] animations:^{ 
toViewController.view.transform = 
CGAffineTransformMakeScale(1.0, 1.0); 
} completion:^(BOOL finished) { 
[transitionContext completeTransition:YES]; 
}]; 
} else if (self.type == AnimationTypeDismiss) { 
//插入“to”视图 
[containerView insertSubview:toViewController.view 
belowSubview:fromViewController.view]; 
//缩小“from”视图,直到其消失 
[UIView animateWithDuration:[self 
transitionDuration:transitionContext] animations:^{ 
fromViewController.view.transform = 
CGAffineTransformMakeScale(0.0, 0.0); 
} completion:^(BOOL finished) { 
[transitionContext completeTransition:YES]; 
}]; 
} 
} 
-(NSTimeInterval)transitionDuration: 
(id)transitionContext { 
return 0.4; 
} 

符合UIViewControllerAnimatedTransitioning协议的任何对象都需要实现animateTransition:和transitionDuration:两个方法。你也可以选择实现@optional方法animationEnded:,它在动画完成后由系统自动调用,相当于completion block,非常方便。