自從iOS7開始開發(fā)者可以靈活的自定義轉(zhuǎn)場(chǎng)動(dòng)畫,而不必局限于子類化UINavigationController來完成自定義. 總的來說, 自定義轉(zhuǎn)場(chǎng)動(dòng)畫有兩種類型: 1. 子類化UINavigationControllerDelegate, 并自定義一個(gè)animator(實(shí)現(xiàn)animated delegate)在重寫協(xié)議中返回; 2. 讓轉(zhuǎn)場(chǎng)動(dòng)畫中的view controller(一般是目標(biāo)VC來實(shí)現(xiàn))實(shí)現(xiàn)UIViewControllerTransitioningDelegate, 并返回animator(與上同). 區(qū)分標(biāo)準(zhǔn)是哪個(gè)object控制動(dòng)畫, 當(dāng)我們想重寫push, pop等導(dǎo)航操作的時(shí)候, 就可以用到第一種方式來自定義; 第二種方式更加靈活, 不僅可以實(shí)現(xiàn)第一種的效果, 而且定制化程度更高(針對(duì)特定的VCs).
在這一篇中, 我們先來講解第一種方式: 通過子類化UINavigationControllerDelegate來自定義轉(zhuǎn)場(chǎng)動(dòng)畫. 先上效果圖:
上文說道, 自定義轉(zhuǎn)場(chǎng)動(dòng)畫有2個(gè)關(guān)鍵點(diǎn):一個(gè)是重寫協(xié)議, 另一個(gè)就是創(chuàng)建自己的動(dòng)畫類. 我們先來看下要重寫那些協(xié)議:
func navigationController(navigationController: UINavigationController, animationControllerForOperation
operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController
toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?{}
func navigationController(navigationController: UINavigationController,
interactionControllerForAnimationController animationController:
UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?{}
第一個(gè)要重寫的方法是返回一個(gè)實(shí)現(xiàn)了UIViewControllerAnimatedTransitioning delegate的動(dòng)畫object, 這個(gè)object定義了轉(zhuǎn)場(chǎng)時(shí)呈現(xiàn)給用戶的動(dòng)畫, 我們稍后再講; 第二個(gè)方法會(huì)返回一個(gè)UIPercentDrivenInteractiveTransition對(duì)象, 這個(gè)對(duì)象是控制用戶和動(dòng)畫交互的controller, 具體來說, 它控制著交互的百分比,存在周期是一個(gè)VC(fromVC)出現(xiàn)和另一個(gè)VC(toVC)消失期間。如果我們想支持用戶通過手勢(shì)進(jìn)行轉(zhuǎn)場(chǎng)的話, 這個(gè)object一定要有, 而且在手勢(shì)識(shí)別的target中添加action來同步更新UIPercentDrivenInteractiveTransition object的進(jìn)度.
下面來講動(dòng)畫. 自定義的動(dòng)畫是NSObject類型, 實(shí)現(xiàn)UIViewControllerAnimatedTransitioning協(xié)議中的2個(gè)方法:
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval{}
func animateTransition(transitionContext: UIViewControllerContextTransitioning){}
第一個(gè)方法是定義動(dòng)畫持續(xù)時(shí)間处渣;第二個(gè)就是定義具體的animation了椿每,代碼如下:
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let toViewController: UIViewController =
transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let fromViewController: UIViewController =
transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
// Get container view from current transitioning context
let containerView: UIView = transitionContext.containerView()!
// Add dest view
containerView.addSubview(toViewController.view)
// Hide toVC first
toViewController.view.alpha = 0
UIView.animateWithDuration(self.transitionDuration(transitionContext), delay: 0, options: [.CurveLinear], animations: {
() -> Void in
// show to view controller
toViewController.view.alpha = 1
fromViewController.view.transform = CGAffineTransformMakeScale(0.1, 0.1)
}) { (finished) -> Void in
// Hide first view controller
fromViewController.view.transform = CGAffineTransformIdentity
// Must use transitionContext.transitionWasCancelled() to notify if the animation cancelled
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
}
該動(dòng)畫實(shí)現(xiàn)了轉(zhuǎn)場(chǎng)時(shí)toViewController透明度漸變?yōu)?, fromViewController scale縮小至原來的十分之一的動(dòng)畫過程倒彰。在這個(gè)方法里拉馋,我們可以自定義很多有創(chuàng)意的動(dòng)畫來完成自定義轉(zhuǎn)場(chǎng), 重點(diǎn)是toVC和fromVC的轉(zhuǎn)換以及生存周期懂鸵,當(dāng)前動(dòng)畫context.
代碼已上傳github, 純Swift實(shí)現(xiàn), <a >點(diǎn)擊這里獲取</a>