Development environment:
- Swift Language Version: Swift 5.0
- Xcode: Version 10.2.1
- Deployment Target: 12.0
UIKit allows customizing view controller’s presentation through UIViewControllerAnimatedTransitioning delegate with two main functions:
- transitionDuration (using:): The function takes information about the time the transition animations takes place. The return value must be the same as the value you used to configure animations in the animateTransition function (using:) .
- animateTransition (using:): Function that allows config transition animations and is called when presenting or dismissing view controller.
Step 1: Initialize the screen
Step 2: Fade Animation Transition
We create class FadeAnimationController and apply the implementation of UIViewControllerAnimatedTransitioning .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | class FadeAnimationController: NSObject, UIViewControllerAnimatedTransitioning { private let presenting: Bool func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.5 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let fromView = transitionContext.view(forKey: .from) else { return } guard let toView = transitionContext.view(forKey: .to) else { return } let container = transitionContext.containerView if presenting { container.addSubview(toView) toView.alpha = 0.0 } else { container.insertSubview(toView, belowSubview: fromView) } UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { if self.presenting { toView.alpha = 1.0 } else { fromView.alpha = 0.0 } }) { _ in let success = !transitionContext.transitionWasCancelled if !success { toView.removeFromSuperview() } transitionContext.completeTransition(success) } } init(presenting: Bool) { self.presenting = presenting } } |
Inside:
- fromView: is the view that appears at the beginning of the transition, or at the end of the cancel transition. For example, when presenting, fromView is the view of viewController1, while when dismissing, fromView is the view of viewController2.
- toView: is the view that appears at the end of the completed transition.
- container: acts as a superview containing the views involved in the transition.
- presenting: Bool variable represents transition type (true when presenting and false when dismissing).
- completeTransition (): The function informs the system that the transition animation has completed.
Step 3: Custom Navigation Controller
We create the TransitionDelegate class and apply the UIViewControllerTransitioningDelegate implementation.
1 2 3 4 5 6 7 8 9 10 11 | final class TransitionDelegate: NSObject, UIViewControllerTransitioningDelegate { func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return FadeAnimationController(presenting: true) } func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return FadeAnimationController(presenting: false) } } |
Inside:
- animationController (forPresented presented:) : function returns object that executes animation transition when present.
- animationController (forDismissed dismissed:) : function returns object that executes animation transition when dismissed.
Step 4: ViewController and ViewController2
We instantiate transitionDelegate object and assign delegate to 2 viewController.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | final class ViewController: UIViewController { let transitionDelegate = TransitionDelegate() override func viewDidLoad() { super.viewDidLoad() self.transitioningDelegate = transitionDelegate } @IBAction func handleTapButton(_ sender: Any) { let vc = storyboard?.instantiateViewController(withIdentifier: "ViewController2") as! ViewController2 vc.transitioningDelegate = transitionDelegate present(vc, animated: true) } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | final class ViewController2: UIViewController { var transitionDelegate: UIViewControllerTransitioningDelegate! override func viewDidLoad() { super.viewDidLoad() self.transitioningDelegate = transitioningDelegate } @IBAction func handleDismissButton(_ sender: Any) { dismiss(animated: true) } } |
Result:
References:
https://itnext.io/learn-ios-custom-view-controller-animation-transition-once-for-all-9db80ad447e
Link github:
https://github.com/oNguyenDucHuyB/CustomTransitionVC/tree/modalTransition