前言
iOS的VCTransition一直是在跟着iOS不断变化着的,最大的感觉就是不断地解耦,动画之间VC的关联变得薄弱,或者都抽象到一个统一的位置,进行处理。下面谈谈:
Navigation、TabBar等切换
这个是最早(传统的)的VC风格了。比如使用如下代码:
-(IBAction)PushA:(id)sender
{
UIStoryboard *story = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
AViewController *aVC = [story instantiateViewControllerWithIdentifier:@"AVCID"];
[self.navigationController pushViewController:aVC animated:YES];
}
这个方法是使用Navigation来管理VCs的一个Transition方式。比较简单,直接。但是耦合性比较大,在VC中必须知道自己要跳转到对应到VC,而且动画要写到对应的VC中,如果动画复杂,会很容易造成VC臃肿起来。
VC容器的Transition
由于iOS5.0后续版本新增了自定义的VC容器,那么从在容器中进行child vc之间到转场,会有专门的方法。比如如下代码:
[self transitionFromViewController:self.goodsCollectionVC
toViewController:self.mainPageVC
duration:SWITCH_VCS_TIME
options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
// do animation things
} completion:^(BOOL finished) {
// do animation completion things
}];
这个方法在容器中切换subVC比较方便,但是只实现了简单的Transition动画,并且依然是有耦合的。因为Container做动画的切换VC的时候,如果动画非常复杂,依然会有动画无法复用的状况。
StoryBoard和Segue
这个是iOS5时提供的转场方式:通过在Storyboard中或代码中定义Push、Modal或 Custom segue,定义一个SegueID,然后需要做Transition的时候,去Perform一个Segue就可以了,代码如下:
[self performSegueWithIdentifier:@"PushSegueID" sender:self];
在执行动画之前,自己的VC就要做些preparation可以在如下代码中调用
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender NS_AVAILABLE_IOS(5_0){}
特别需要说一下,如果动画处理复杂的,通过Custom Segue,就可以把动画挪到自定义segue中,降低sourceVC的代码量,动画也可以解耦甚至抽象。主要步骤就有两个:
– 在Storybaord或代码中实例化自定义的segue。
– 自定义Segue类复写perform方法。
关键代码如下:
-(void)perform
{
id sourceVC = self.sourceViewController;
id destVC = self.destinationViewController;
//Do animation
}
segue 最关键的两个property,一个是sourceViewController,一个是destinationViewController,就实现一个动画而言,这两个变量就够了。
iOS7的Transition
iOS7提供了新的transition方式。默认提供了Present和Push的抽象动画,新增了percent的手势交互动画。例如,如果要自定义navigation push的动画就可以实现一个支持UIViewControllerAnimatedTransitioning的对象。在这个transition对象中,来设计自己的动画。和segue类似,代码可见:
-(void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *destController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController *fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIView *containerView = [transitionContext containerView];
[containerView addSubview:destController.view];
}
和Segue相同的是,都可以通过对象来获取Source和DestinationVC。不同的是,iOS7新提供的Transition提供了ContainerView,来做动画交互的容器。
对于外部而言,在代理中制定对应的Custom Transition对象即可使用他们了,可定制化更高:
比如在VC Controller中实例化对应的代理方法:
-(id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
if (someCondition)
{
_naviTransitioning.operation = operation;
return _naviTransitioning;
}
return nil;
}
至于iOS7的UIPercentDrivenInteractiveTransition,这里不展开讲了,具体可以搜搜相关文档。
经过Transition的不断强化,iOS7新增的Transition,大大增强了动画的复用性,降低了耦合度,增加了交互性,给编码人员提供更多福利。