一 设置控制器代理 transitioningDelegate
pictureVC.transitioningDelegate = self
二 设置转场模式 modalPresentationStyle
pictureVC.modalPresentationStyle = UIModalPresentationStyle.Custom
默认的转场 系统present之后 底层的view被移除出控制器
自定义转场 底层的view依旧在 新的视图只是遮盖在上面
三 遵守协议 UIViewControllerTransitioningDelegate
- 实现代理方法
extension HomeTableViewController: UIViewControllerTransitioningDelegate {
/**
返回提供转场动画的对象 这个对象可以是任何一个对象 只要遵守了 UIViewControllerAnimatedTransitioning 协议
*/
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
/**
返回提供解除动画的对象
*/
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
}
- 此时两个方法会报错 因为 return self 没有遵守协议
UIViewControllerAnimatedTransitioning
在写一个类扩展遵守协议
extension HomeTableViewController: UIViewControllerAnimatedTransitioning {
}
- 此时错误会转移到下边的类扩展 因为没有实现协议方法 协议方法中有两个必须一个可选
extension HomeTableViewController: UIViewControllerAnimatedTransitioning {
// 转场动画时长
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 2.0
}
/**
自定义转场动画
- parameter transitionContext: 提供了转场动画所需要的元素
*/
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
// 此方法必须实现(API 注明)
transitionContext.completeTransition(true)
}
}
此时运行代码 发现不会弹出控制器了 因为只要实现了此方法 就需要自己写动画
func animateTransition(transitionContext: UIViewControllerContextTransitioning)
此时需要先把 上边的 返回解除转场动画的方法注释掉
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
extension HomeTableViewController: UIViewControllerAnimatedTransitioning {
// 转场动画时长
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 2.0
}
/**
自定义转场动画 只要实现了此方法 就需要自己写动画
- parameter transitionContext: 提供了转场动画所需要的元素
- transitionContext.completeTransition(true) 动画结束后必须调用
- containerView() 容器视图
- viewForKey 获取到转场的视图 ios8.0
*/
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
// MainViewController 弹出视图的控制器
let fromVc = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
// 要展现的控制器
let toVc = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!
transitionContext.containerView()?.addSubview(toView)
toView.alpha = 0.0
UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
toView.alpha = 1.0
}) { (_) in
// 此方法必须实现(API 注明)
// 动画结束之后一定要执行,如果不执行,系统会一直等待,无法进行后续交互
transitionContext.completeTransition(true)
}
}
}
此时已经能够实现转场动画了 接下来解决解除转场, 不然关闭的时候 直接下去没有别的动画
打开刚刚注释掉的方法
定义属性记录 是否已经转场 不然拿到的toView会有问题
// 是否转场
private var isPresent : Bool = true
extension HomeTableViewController: UIViewControllerTransitioningDelegate {
/**
返回提供转场动画的对象 这个对象可以是任何一个对象 只要遵守了 UIViewControllerAnimatedTransitioning 协议
*/
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
isPresent = true
return self
}
/**
返回提供解除动画的对象
*/
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
isPresent = false
return self
}
}
extension HomeTableViewController: UIViewControllerAnimatedTransitioning {
// 转场动画时长
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 2.0
}
/**
自定义转场动画 只要实现了此方法 就需要自己写动画
- parameter transitionContext: 提供了转场动画所需要的元素
- transitionContext.completeTransition(true) 动画结束后必须调用
- containerView() 容器视图
- viewForKey 获取到转场的视图 ios8.0
*/
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
// MainViewController 弹出视图的控制器
// let fromVc = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
// 要展现的控制器
// let toVc = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
if isPresent {
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!
transitionContext.containerView()?.addSubview(toView)
toView.alpha = 0.0
UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
toView.alpha = 1.0
}) { (_) in
// 此方法必须实现(API 注明)
// 动画结束之后一定要执行,如果不执行,系统会一直等待,无法进行后续交互
transitionContext.completeTransition(true)
}
} else {
// 解除转场的时候 fromVc 是 present出来的控制器 反了一下
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
fromView.alpha = 0.0
}, completion: { (_) in
fromView.removeFromSuperview()
// 解除转场 会把容器视图和内部视图 销毁
transitionContext.completeTransition(true)
})
}
}
}