自定義動畫切換的相關(guān)主要API
在學(xué)習(xí)自定義轉(zhuǎn)場動畫之前,我們一起來看看相關(guān)SDK以及它們的關(guān)系和典型用法。這幾個接口和類的名字都比較類似,但是還是能比較好的描述出各自的職能,一開始可能比較容易迷惑,但是當(dāng)我們自己手動實現(xiàn)一兩個例子過后,它們之間的關(guān)系就比較明了。
@protocol UIViewControllerContextTransitioning
這個接口用來提供切換上下文給開發(fā)者使用,包含了從哪個VC到哪個VC等各類信息,一般不需要開發(fā)中自己實現(xiàn)。具體來說,iOS7的自定義切換目的之一就是切換相關(guān)代碼解藕,在進(jìn)行VC切換時,做切換效果實現(xiàn)的時候需要切換前后VC的一些信息,系統(tǒng)在新加入的API的比較的地方都會提供一個實現(xiàn)了該接口的對象以供我們使用。
對于切換的動畫實現(xiàn)來說,這個接口種最重要的方法有:
1. -(UIView *)containerView; VC切換所發(fā)生的view容器,開發(fā)者應(yīng)該將切出的view移除,將切入的view加入到該view容器中。
2. -(UIViewController *)viewControllerForKey:(NSString *)key; 提供一個key,返回對應(yīng)的VC?,F(xiàn)在的SDK中key的選擇只有UITransitionContextFromViewControllerKey和UITransitionContextToViewControllerKey兩種,分別表示將要切出和切入的VC。
3. -(CGRect)initialFrameForViewController:(UIViewController *)vc; 某個VC的初始位置,可以用來做動畫的計算。
4. -(CGRect)finalFrameForViewController:(UIViewController *)vc; 與上面的方法對應(yīng),得到切換結(jié)束時某個VC應(yīng)在的frame。
5. -(void)completeTransition:(BOOL)didComplete; 向這個context報告切換已經(jīng)完成。
@protocol?UIViewControllerAnimatedTransitioning
這個接口負(fù)責(zé)切換的具體內(nèi)容,也即“切換中應(yīng)該發(fā)生什么”。開發(fā)者在做自定義切換效果時大部分代碼會是用來實現(xiàn)這個接口。它只有兩個方法需要我們實現(xiàn):
1. -(NSTimeInterval)transitionDuration:(id < UIViewControllerContextTransitioning >)transitionContext; 系統(tǒng)給出一個切換上下文,我們根據(jù)上下文環(huán)境返回這個切換所需要的花費時間(一般就返回動畫的時間就好了,SDK會用這個時間來在百分比驅(qū)動的切換中進(jìn)行幀的計算,后面再詳細(xì)展開)。
2. -(void)animateTransition:(id < UIViewControllerContextTransitioning >)transitionContext; 在進(jìn)行切換的時候?qū)⒄{(diào)用該方法,我們對于切換時的UIView的設(shè)置和動畫都在這個方法中完成。
@protocol?UIViewControllerTransitioningDelegate
這個接口的作用比較簡單單一,在需要VC切換的時候系統(tǒng)會像實現(xiàn)了這個接口的對象詢問是否需要使用自定義的切換效果。這個接口共有四個類似的方法:
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;
前兩個方法是針對動畫切換的,我們需要分別在呈現(xiàn)VC和解散VC時,給出一個實現(xiàn)了UIViewControllerAnimatedTransitioning接口的對象(其中包含切換時長和如何切換)。后兩個方法涉及交互式切換,之后再說。
介紹了理論上的東西,我們來實現(xiàn)一下,Demo來了~~
首先我們需要新建一個實現(xiàn)了UIViewControllerAnimatedTransitioning協(xié)議的類。

解釋一下這個實現(xiàn):
我們首先需要得到參與切換的兩個ViewController的信息,使用context的方法拿到它們的參照;
對于要呈現(xiàn)的VC,我們希望它從屏幕下方出現(xiàn),因此將初始位置設(shè)置到屏幕下邊緣;
將view添加到containerView中;
開始動畫。這里的動畫時間長度和切換時間長度一致,都為0.8s。usingSpringWithDamping的UIView動畫API是iOS7新加入的,描述了一個模擬彈簧動作的動畫曲線,我們在這里只做使用,更多信息可以參看相關(guān)文檔;(順便多說一句,iOS7中對UIView動畫添加了一個很方便的Category,UIViewKeyframeAnimations。使用其中方法可以為UIView動畫添加關(guān)鍵幀動畫)
在動畫結(jié)束后我們必須向context報告VC切換完成,是否成功(在這里的動畫切換中,沒有失敗的可能性,因此直接pass一個YES過去)。系統(tǒng)在接收到這個消息后,將對VC狀態(tài)進(jìn)行維護(hù)。
接下來我們實現(xiàn)一個UIViewControllerTransitioningDelegate,應(yīng)該就能讓它工作了。我們現(xiàn)在在ViewController當(dāng)中來直接實現(xiàn)這個接口。如下

參考https://onevcat.com/2013/10/vc-transition-in-ios7/