UINavigationController内部页面跳转默认为左右切换,但是当我们想向上弹出进入界面,或者向下离开界面时,需要实现UINavigationControllerDelegate 协议自行控制页面的动画(否则直接在navVc上叠加动画会导致动画结束后的那个页面,自动加了异常动画),本文介绍这个实现方案。
定义一个类实现 UIViewControllerAnimatedTransitioning协议,实现下面的函数:
class NavigationControllerAnimation: NSObject, UIViewControllerAnimatedTransitioning {
let operation: UINavigationController.Operation
init(operation: UINavigationController.Operation) {
self.operation = operation
super.init()
}
//页面过渡动画时间
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
//加页面过渡的动画
public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { return }
let containerView = transitionContext.containerView
if operation == .push {
// do your animation for push
toViewController.view.frame = containerView.bounds.offsetBy(dx: 0, dy: containerView.frame.size.height)
fromViewController.view.frame = containerView.bounds
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: [ UIView.AnimationOptions.curveEaseOut ],
animations: {
toViewController.view.frame = containerView.bounds
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
} else if operation == .pop {
// do your animation for pop
containerView.addSubview(toViewController.view)
containerView.addSubview(fromViewController.view)//containerView 上加的view在动画结束后一段时间后被释放了
fromViewController.view.frame = containerView.bounds
// toViewController.view.frame = containerView.bounds
UIView.animate(withDuration: transitionDuration(using: transitionContext),
animations: {
fromViewController.view.frame = containerView.bounds.offsetBy(dx: 0, dy: containerView.frame.size.height)
},
completion: { (finished) in
transitionContext.completeTransition(true)
})
}
}
}
UINavigationController 添加delegate
class BaseNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
}
实现delegate的协议 ,返回本文最开始定义的类的对象,这里只要返回nil 就会是默认的动画方式(所以可以按照需求切换界面过渡动画)
extension BaseNavigationController : UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return NavigationControllerAnimation(operation: operation)
}
}
参考:
https://stackoverflow.com/questions/2215672/how-to-change-the-push-and-pop-animations-in-a-navigation-based-app