要建立定制切换效果,你须要作以下的事情: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
用于标识在动画完成后应该存在的视图。