在swift中實現(xiàn)自定義轉(zhuǎn)場動畫

1.需求確認

? ? ? 在HomeViewController中, 點擊TitleButton, 通過自定義轉(zhuǎn)場動畫的方式modal出一小塊的PopoverViewController

2.類索引

? ? ? 1) HomeViewController : BaseViewController
-- "源控制器", 負責(zé)發(fā)起自定義轉(zhuǎn)場
? ? ? 2) PopoverViewController : UIViewController
-- "目標(biāo)控制器", 通過自定義轉(zhuǎn)場而被展現(xiàn)
? ? ? 3) PopoverPresentationController : UIPresentationController
-- "轉(zhuǎn)場控制器", 負責(zé)配置自身容器屬性, 將目標(biāo)控制器的view添加到容器中, 容器本質(zhì)也是一個view
? ? ? 4) PopoverAnimator : NSObject
-- 自定義轉(zhuǎn)場動畫類, 用于將下面兩個代理中的方法從源控制器中進行抽離, 使源控制器只保留邏輯代碼, 保證其代碼的整潔和優(yōu)雅
? ? ? 5) UIViewControllerTransitioningDelegate
?-- 常用三個代理方法, 用于告訴系統(tǒng)誰是轉(zhuǎn)場控制器, 誰負責(zé)轉(zhuǎn)場動畫的開始, 誰負責(zé)轉(zhuǎn)場動畫的結(jié)束
? ? ? 6) UIViewControllerAnimatedTransitioning
-- 常用兩個代理方法, 用于告訴系統(tǒng)轉(zhuǎn)場動畫的持續(xù)時間與實現(xiàn)

3.實現(xiàn)步驟


1) 設(shè)置目標(biāo)控制器的代理對象

popoverViewController.transitioningDelegate = 自定義轉(zhuǎn)場動畫類的實例化對象

2) 設(shè)置目標(biāo)控制器的轉(zhuǎn)場樣式

popoverViewController.modalPresentationStyle= UIModalPresentationStyle.Custom

3) 自定義轉(zhuǎn)場控制器類 PopoverPresentationController : UIPresentationController
在這個類中, 著重使用了兩個屬性, 并重寫兩個方法:

containerView : 容器屬性, 所有被展現(xiàn)的東西都在這個view內(nèi)部
presentedView() : 返回目標(biāo)控制器的view

init(presentedViewController, presentingViewController)
初始化方法, 記得調(diào)用'super.'對父類初始化
第一個參數(shù): 目標(biāo)控制器
第二個參數(shù): 在Xcode6為nil, Xcode7為野指針

containerViewWillLayoutSubviews()
容器布局方法, 該方法會在轉(zhuǎn)場前進行調(diào)用, 對容器內(nèi)的視圖進行統(tǒng)一配置(包括: 目標(biāo)控制器的view.frame、coverView等)

4) 實現(xiàn)UIViewControllerTransitioningDelegate的最主要代理方法

presentationControllerForPresentedViewController(presented,presenting, source)
-> UIPresentationController?
該代理方法告訴系統(tǒng), 誰是轉(zhuǎn)場控制器
參數(shù)一: 目標(biāo)控制器
參數(shù)二: 在Xcode6為nil, Xcode7為野指針
參數(shù)三: 源控制器
返回值: 轉(zhuǎn)場控制器

5) 實現(xiàn)UIViewControllerTransitioningDelegate的另外兩個代理方法

animationControllerForPresentedController(presented, presenting, source)
-> UIViewControllerAnimatedTransitioning?
該代理方法告訴系統(tǒng), 誰負責(zé)轉(zhuǎn)場動畫的展現(xiàn), 在展現(xiàn)開始前被調(diào)用
返回值: 簽訂UIViewControllerAnimatedTransitioning協(xié)議的對象, 這里返回轉(zhuǎn)場動畫類

animationControllerForDismissedController(dismissed)
-> UIViewControllerAnimatedTransitioning?
該代理方法告訴系統(tǒng), 誰負責(zé)轉(zhuǎn)場動畫的消失, 在消失開始前被調(diào)用
返回值: 簽訂UIViewControllerAnimatedTransitioning協(xié)議的對象, 這里返回轉(zhuǎn)場動畫類

6) 實現(xiàn)UIViewControllerAnimatedTransitioning的兩個代理方法

transitionDuration(transitionContext) ->NSTimeInterval
該代理方法告訴系統(tǒng), 轉(zhuǎn)場動畫的執(zhí)行時間

animateTransition(transitionContext)
在該代理方法中完成動畫的實現(xiàn), 無論展現(xiàn)還是消失,都會調(diào)用這個方法
參數(shù): transitionContext, 里面包含了動畫需要的所有參數(shù)!
通過 transitionContext.viewControllerForKey(key) 獲取目標(biāo)控制器和源控制器
通過 transitionContext.viewForKey(key) 獲取展現(xiàn)的view和消失的view
通過 transitionContext.containerView 獲取轉(zhuǎn)場控制器的容器屬性
通過 transitionDuration(transitionContext) 設(shè)置動畫持續(xù)時間
通過 transitionContext.completeTransition(true), 動畫完成時告訴系統(tǒng), 該步必須有!

7) 一切準(zhǔn)備就緒, 調(diào)用modal方法吧

presentViewController(homeVC, animated:true, completion:nil)

4.注意事項


1) 自定義轉(zhuǎn)場需要iOS8以上版本?

2) 默認轉(zhuǎn)場會將源控制器的view替換成目標(biāo)控制器的view, 而自定義轉(zhuǎn)場,不會移除源控制器的view

3) 重寫步驟5和6里面的代理方法后, 系統(tǒng)自帶的轉(zhuǎn)場動畫(從下至上)就已經(jīng)沒有了

4) 在代理方法animateTransition(transitionContext)中, 通過使用transitionContext.viewForKey(key)獲取到要展現(xiàn)的視圖后,一定要將其添加到容器中,?否則彈窗彈不出來!

5) 在轉(zhuǎn)場動畫完成后, 一定要調(diào)用transitionContext.completeTransition(true), 否則會產(chǎn)生各種未知的問題(如同在layoutSubviews()中不調(diào)用super一樣)

6) 在UIView.animateWithDuration()中, 如果調(diào)用了CGAffineTransformMakeScale等參數(shù)類型為CGFloat的方法, 填0.0會沒有動畫, 由于系統(tǒng)缺陷導(dǎo)致CGFloat類型是不準(zhǔn)確的.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容