0行代碼集成非死book和推ter的Modal動畫
用過非死book和推ter的同學應該尤其喜歡他們的動畫,但是動人心弦的動畫都是用時間堆出來的,可是程序員的時間... 各位同學,寫完代碼,就去陪老婆吃一頓飯吧,程序員老婆不容易。
現在進入正題。沒錯,就是告訴你0行代碼擁有非死book和推ter這個動畫。
要實現這個功能分兩步走:第一步,先實現這個動畫。第二步,0行代碼集成到項目。也就是,你不用改原有項目的任何代碼,只要把寫好的動畫代碼拖進項目,以后所有的Modal就擁有這個動畫了。
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion
好,準備好了嗎?現在開始。
第一步:先實現這個動畫
-
首先我們來分析一下這個動畫,這個動畫就是在Modal的時候拿到當前控制器的View,然后在Modal的過程中將這個View的尺寸縮小。然后在Dismiss的時候拿到這個View,將它尺寸恢復成原有的大小。就這么多了。
-
怎么在modal動畫中拿到當前的控制器的View?這個很簡單,只要你設置動畫樣式為自定義,并且成為彈出動畫的代理,就像這樣:
self.modalTransitionStyle = UIModalPresentationCustom; viewControllerToPresent.transitioningDelegate = self;
然后在代理方法中,會詢問轉場動畫的提供者,此時,你再去新建一個JPTransitionManager作為轉場動畫的提供者。
// 詢問轉場動畫的提供者 - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source; - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;
-
在這個轉場動畫的提供者里,我們繼承NSObject,然后遵守
UIViewControllerAnimatedTransitioning協議,然后實現協議中這兩個方法:- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext; - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
第一個方法是詢問動畫的時長的。第二個方法中我們可以拿到準備做Modal動畫的上下文transitionContext,在上下文中我們就可以通過:UITransitionContextFromViewControllerKey和UITransitionContextToViewControllerKey兩個key拿到當前的控制器和即將彈出的控制器。
-
控制器都拿到了,我們就可以拿到控制器對應的View進行動畫了。
第二步:0行代碼集成到項目
為什么要強調0行代碼集成到項目?
- 剛開始寫代碼的時候,項目老大并沒有說要這個動畫,你項目都快結束了,他說這個動畫挺好,我們也做一個吧(程序員轉過身:XXX臟話)。這個時候你已經寫了幾百個Modal動畫的代碼了,你不可能一個一個去找去改吧?
- 幾百行你改完了,你以為終于完事了,這件事就過去了,結果產品經理一個月以后又跑過來說,這個功能我們還是砍掉吧。(程序員大聲:XXXXXX很臟的話)。
所以,這個時候低耦合易集成就顯得特別重要。
為了處理這樣的需求,所以采用hook方案,結合runtime來解決。hook就是鉤子的意思。
- 我們要用這個鉤子把系統所有的Modal動畫的實現都鉤出來,然后再把我們自己寫的pop動畫也給鉤出來。
- 然后再運用動態方法交換,將這系統的Modal動畫和自己的pop動畫的實現相互替換。
- 所以以后,我們再調用系統的Modal動畫的時候,實際上會去方法實現里找我們自己的pop動畫去執行。這也就是為什么可以0行代碼集成這個功能的原因。
- 也有可能我們在某些情況下不需要pop動畫,比如說照片瀏覽器。這種情況很少,所以你只需要寫很少的代碼,去調用我們自己的pop動畫。當調用我們自己的pop動畫的時候,我們的鉤子會去找系統的Modal動畫去執行。
思路就到這里了,具體的實現細節,還需要您自己去Github下載 demo 。
One more thing ?
如果您對“hook技術”想有一個相對全面的了解,或許可以參見我的另外一篇文章“1行代碼快速集成按鈕延時處理(hook實戰)”。我在這篇文章詳細的闡述了鄙人對“hook技術”的見解。
來自:http://www.jianshu.com/p/910d7825f06a