要建立定製切換效果,你須要作以下的事情:html
UIViewControllerAnimatedTransitioning
協議。在這個類中將編寫代碼來執行動畫,這個類將做爲動畫控制器被關聯。UIViewControllerAnimatedTransitioning
協議UIViewControllerAnimatedTransitioning
協議用於描述視圖控制器切換的動畫效果,咱們能夠經過實現這個協議,並利用該類來實如今視圖間切換過程當中的動畫效果。能夠在這個類中定義一個動畫對象,這個動畫對象建立一個視圖控制器在一個固定的時間內出現/消失在屏幕上的動畫效果。使用這個協議建立的動畫 必須 是沒法交互的。若是要建立能夠交互的切換,必須混合動畫對象和另外一個控制動畫時間的對象。ios
在動畫對象中,實現transitionDuration:
方法來指定切換的過程,實現animateTransition:
方法來建立動畫。在切換過程當中使用的對象的信息在一個上下文對象中傳遞給animateTransition:
方法。使用這個上下文對象(UIViewControllerContextTransitioning
)提供的信息,來移動目標視圖控制器的視圖在指定的區間內出現/消失在屏幕上。swift
從一個實現了UIViewControllerTransitioningDelegate
協議的切換委託對象中建立一個動畫對象。當呈現一個視圖控制器時,設置呈現類型爲UIModalPresentationCustom
,並指定切換委託到視圖控制器的transitioningDelegate
屬性。視圖控制器從切換委託中接受動畫對象,並使用這個切換委託來執行動畫。能夠爲視圖控制器的出現、消失分別定製不一樣的動畫對象。app
爲了添加用戶交互到一個視圖控制器的切換效果中,必須一塊兒使用一個動畫對象和一個交互動畫對象(一個實現UIViewControllerInteractiveTransitioning
協議的定製類)。ide
執行切換學習
切換過程:動畫
具體實現以下所示。ui
import Foundation import UIKit class AnimatedTransitioning: NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { return 5 } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)! let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)! let finalFrameForVC = transitionContext.finalFrameForViewController(toViewController) let containerView = transitionContext.containerView() let bounds = UIScreen.mainScreen().bounds toViewController.view.frame = CGRectOffset(finalFrameForVC, 0, bounds.size.height) containerView.addSubview(toViewController.view) UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: .CurveLinear, animations: { fromViewController.view.alpha = 0.5 toViewController.view.frame = finalFrameForVC }, completion: { finished in transitionContext.completeTransition(true) fromViewController.view.alpha = 1.0 }) } }
UIViewControllerTransitioningDelegate
import UIKit class ViewController: UIViewController, UIViewControllerTransitioningDelegate { // ... let customPresentAnimationController = CustomPresentAnimationController() let customDismissAnimationController = CustomDismissAnimationController() override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "showAction" { let toViewController = segue.destinationViewController as! UIViewController // 用於給目標視圖指定切換動畫代理 toViewController.transitioningDelegate = self } } // 用於視圖出現 func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return customPresentAnimationController } // 用於視圖消失 func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return customDismissAnimationController } // ... }
UIViewControllerInteractiveTransitioning
注意:.net
UIPercentDrivenInteractiveTransition
是UIViewControllerInteractiveTransitioning
的子類代理
import UIKit class CustomInteractionController: UIPercentDrivenInteractiveTransition { var navigationController: UINavigationController! var shouldCompleteTransition = false var transitionInProgress = false var completionSeed: CGFloat { return 1 - percentComplete } func attachToViewController(viewController: UIViewController) { navigationController = viewController.navigationController setupGestureRecognizer(viewController.view) } private func setupGestureRecognizer(view: UIView) { view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: "handlePanGesture:")) } func handlePanGesture(gestureRecognizer: UIPanGestureRecognizer) { let viewTranslation = gestureRecognizer.translationInView(gestureRecognizer.view!.superview!) switch gestureRecognizer.state { case .Began: transitionInProgress = true navigationController.popViewControllerAnimated(true) case .Changed: var const = CGFloat(fminf(fmaxf(Float(viewTranslation.x / 200.0), 0.0), 1.0)) shouldCompleteTransition = const > 0.5 updateInteractiveTransition(const) case .Cancelled, .Ended: transitionInProgress = false if !shouldCompleteTransition || gestureRecognizer.state == .Cancelled { cancelInteractiveTransition() } else { finishInteractiveTransition() } default: println("Swift switch must be exhaustive, thus the default") } } }
UIViewControllerContextTransitioning
UIViewControllerContextTransitioning
協議的方法爲切換的兩個視圖控制器提供上下文信息。在一次切換當中,切換中使用的動畫對象從UIKit
接受一個完整的配置上下文對象,UIViewControllerAnimatorTransitioning
或UIViewControllerInteractiveTransitioning
協議的方法從提供的對象中提取它們須要的信息。
訪問切換對象
containerView()
:獲取在動畫執行過程當中做爲父視圖的視圖。viewControllerForKey(_:)
:Key可選值參數見下方的__常量__部分。viewForKey(_:)
獲取切換框體矩形
finalFrameForViewController
用於獲取指定的視圖控制器視圖最終的框體矩形。
獲取切換行爲
反饋切換進度
completeTransition(_:)
必須updateInteractiveTransition(_:)
必須finishInteractiveTransition()
必須cancelInteractiveTransition()
必須transitionWasCancelled()
必須獲取屏幕方向
常量
View Controller Transition Keys
用於標識在切換執行過程當中所存在的視圖控制器,包含兩個值,一個是UITransitionContextFromViewControllerKey
用於標識在動畫開始時就已經存在的視圖控制器,一個是UITransitionContextToViewControllerKey
用於標識在動畫完成後應該存在的視圖控制器。
View Transition Keys
用於標識在切換執行過程當中所存在的視圖,包含兩個值,一個是UITransitionContextFromViewKey
用於標識在動畫開始時就已經存在的視圖,一個是UITransitionContextToViewKey
用於標識在動畫完成後應該存在的視圖。