自定义ViewController动画切换
自定义动画切换的相关主要API
在学习自定义转场动画之前,我们一起来看看相关SDK以及它们的关系和典型用法。这几个接口和类的名字都比较类似,但是还是能比较好的描述出各自的职能,一开始可能比较容易迷惑,但是当我们自己手动实现一两个例子过后,它们之间的关系就比较明了。
@protocol UIViewControllerContextTransitioning
这个接口用来提供切换上下文给开发者使用,包含了从哪个VC到哪个VC等各类信息,一般不需要开发中自己实现。具体来说,iOS7的自定义切换目的之一就是切换相关代码解藕,在进行VC切换时,做切换效果实现的时候需要切换前后VC的一些信息,系统在新加入的API的比较的地方都会提供一个实现了该接口的对象以供我们使用。
对于切换的动画实现来说,这个接口种最重要的方法有:
1. -(UIView *)containerView; VC切换所发生的view容器,开发者应该将切出的view移除,将切入的view加入到该view容器中。
2. -(UIViewController *)viewControllerForKey:(NSString *)key; 提供一个key,返回对应的VC。现在的SDK中key的选择只有UITransitionContextFromViewControllerKey和UITransitionContextToViewControllerKey两种,分别表示将要切出和切入的VC。
3. -(CGRect)initialFrameForViewController:(UIViewController *)vc; 某个VC的初始位置,可以用来做动画的计算。
4. -(CGRect)finalFrameForViewController:(UIViewController *)vc; 与上面的方法对应,得到切换结束时某个VC应在的frame。
5. -(void)completeTransition:(BOOL)didComplete; 向这个context报告切换已经完成。
@protocol UIViewControllerAnimatedTransitioning
这个接口负责切换的具体内容,也即“切换中应该发生什么”。开发者在做自定义切换效果时大部分代码会是用来实现这个接口。它只有两个方法需要我们实现:
1. -(NSTimeInterval)transitionDuration:(id < UIViewControllerContextTransitioning >)transitionContext; 系统给出一个切换上下文,我们根据上下文环境返回这个切换所需要的花费时间(一般就返回动画的时间就好了,SDK会用这个时间来在百分比驱动的切换中进行帧的计算,后面再详细展开)。
2. -(void)animateTransition:(id < UIViewControllerContextTransitioning >)transitionContext; 在进行切换的时候将调用该方法,我们对于切换时的UIView的设置和动画都在这个方法中完成。
@protocol UIViewControllerTransitioningDelegate
这个接口的作用比较简单单一,在需要VC切换的时候系统会像实现了这个接口的对象询问是否需要使用自定义的切换效果。这个接口共有四个类似的方法:
1. -(id< UIViewControllerAnimatedTransitioning >)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
2. -(id< UIViewControllerAnimatedTransitioning >)animationControllerForDismissedController:(UIViewController *)dismissed;
3. -(id< UIViewControllerInteractiveTransitioning >)interactionControllerForPresentation:(id < UIViewControllerAnimatedTransitioning >)animator;
4. -(id< UIViewControllerInteractiveTransitioning >)interactionControllerForDismissal:(id < UIViewControllerAnimatedTransitioning >)animator;
前两个方法是针对动画切换的,我们需要分别在呈现VC和解散VC时,给出一个实现了UIViewControllerAnimatedTransitioning接口的对象(其中包含切换时长和如何切换)。后两个方法涉及交互式切换,之后再说。
介绍了理论上的东西,我们来实现一下,Demo来了~~
首先我们需要新建一个实现了UIViewControllerAnimatedTransitioning协议的类。
解释一下这个实现:
我们首先需要得到参与切换的两个ViewController的信息,使用context的方法拿到它们的参照;
对于要呈现的VC,我们希望它从屏幕下方出现,因此将初始位置设置到屏幕下边缘;
将view添加到containerView中;
开始动画。这里的动画时间长度和切换时间长度一致,都为0.8s。usingSpringWithDamping的UIView动画API是iOS7新加入的,描述了一个模拟弹簧动作的动画曲线,我们在这里只做使用,更多信息可以参看相关文档;(顺便多说一句,iOS7中对UIView动画添加了一个很方便的Category,UIViewKeyframeAnimations。使用其中方法可以为UIView动画添加关键帧动画)
在动画结束后我们必须向context报告VC切换完成,是否成功(在这里的动画切换中,没有失败的可能性,因此直接pass一个YES过去)。系统在接收到这个消息后,将对VC状态进行维护。
接下来我们实现一个UIViewControllerTransitioningDelegate,应该就能让它工作了。我们现在在ViewController当中来直接实现这个接口。如下
ViewController参考https://onevcat.com/2013/10/vc-transition-in-ios7/