参考资料:
Apple 开发文档 Customizing the Transition Animations
WWDC 2013 Custom Transitions Using View Controllers
图例:
跳转的动画有很多,全部可以自定义
创建自定义转换你必须遵循三个步骤:
- 1、创建一个类,并实现了
UIViewControllerAnimatedTransitioning
协议 - 2、创建一个类作为
UINavigationControllerDelegate
过渡代理,实现对应方法 - 3、在将要
push
的控制器内设置导航控制器的代理为自定义的代理(步骤2的代理类)
核心代码
1、创建一个类,并实现了 UIViewControllerAnimatedTransitioning
协议
class CustomNaviAnimatedTransition: NSObject {
var isPushed: Bool?
// 通过 static let 创建单例
static let shared = CustomNaviAnimatedTransition()
// 构造函数,init前加private修饰,表示原始构造方法只能自己使用,外界不发调用
private override init() { }
}
/// 从左往右进,从左往右出
extension CustomNaviAnimatedTransition: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.5
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let fromView = transitionContext.view(forKey: .from)!
let toView = transitionContext.view(forKey: .to)!
let containerView = transitionContext.containerView
if isPushed == true {
containerView.addSubview(toView)
toView.frame.origin.x = -toView.bounds.width
UIView.animate(withDuration: 0.3, animations: {
toView.frame.origin.x = 0
}, completion: { (finished) in
if finished {
transitionContext.completeTransition(finished)
}
})
} else {
containerView.insertSubview(toView, belowSubview: fromView)
UIView.animate(withDuration: 0.3, animations: {
fromView.frame.origin.x = fromView.frame.width
}, completion: { (finished) in
if finished {
transitionContext.completeTransition(finished)
}
})
}
}
}
2、创建一个类作为 UINavigationControllerDelegate
过渡代理,实现对应方法
class CustomNaviAnimateDelagete: NSObject, UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animationTransition = CustomNaviAnimatedTransition.shared
animationTransition.isPushed = operation.rawValue == 1
return animationTransition
}
}
3、在将要 push
的控制器内设置导航控制器的代理为自定义的代理(步骤2的代理类)
注意:代理不能为局部变量
class ViewController: UIViewController {
var cnaDelegate = CustomNaviAnimateDelagete()
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.delegate = cnaDelegate
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let vc = TempViewController()
navigationController?.pushViewController(vc, animated: true)
}
}