The best way to achieve that is to create custom push and pop animation by conforming UIViewControllerAnimatedTransitioning
protocol:-
//CustomPushAnimation class
import UIKit
class CustomPushAnimation: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.2
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerVw = transitionContext.containerView
let fromViewController = transitionContext.viewController(forKey: .from)
let toViewController = transitionContext.viewController(forKey: .to)
guard let fromVc = fromViewController, let toVc = toViewController else { return }
let finalFrame = transitionContext.finalFrame(for: toVc)
//Below line will start from left
toVc.view.frame = finalFrame.offsetBy(dx: -finalFrame.size.width/2, dy: 0)
containerVw.addSubview(toVc.view)
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
toVc.view.frame = finalFrame
fromVc.view.alpha = 0.5
}, completion: {(finished) in
transitionContext.completeTransition(finished)
fromVc.view.alpha = 1.0
})
}
}
//CustomPopAnimation class
import UIKit
class CustomPopAnimation: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.2
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
let fromViewController = transitionContext.viewController(forKey: .from)
let toViewController = transitionContext.viewController(forKey: .to)
guard let fromVc = fromViewController,
let toVc = toViewController,
let snapshotView = fromVc.view.snapshotView(afterScreenUpdates: false)
else { return }
let finalFrame = transitionContext.finalFrame(for: fromVc)
toVc.view.frame = finalFrame
containerView.addSubview(toVc.view)
containerView.sendSubview(toBack: toVc.view)
snapshotView.frame = fromVc.view.frame
containerView.addSubview(snapshotView)
fromVc.view.removeFromSuperview()
UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
//Below line will start from right
snapshotView.frame = finalFrame.offsetBy(dx: -finalFrame.size.width, dy: 0)
}, completion: {(finished) in
snapshotView.removeFromSuperview()
transitionContext.completeTransition(finished)
})
}
}
And last you need to present the new View controller with setting
animation flag to true otherwise it will not work
//Below code should be inside YourViewController
let vc = UIStoryboard(name: "storyboardName", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerIdentifier") let navigationController = BaseNavigationController(rootViewController: vc)
navigationController.transitioningDelegate = self
present(navigationController, animated: true, completion: nil)
You also need to conform UIViewControllerTransitioningDelegate
protocol in order to work animation
extension YourViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return customPushAnimation
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return customPopAnimation
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…