Custom Transition Animation for UIViewController using Core Animation

In this tutorial you are going to learn how to make custom animation while moving from a view controller to another using the API provided by the Core Animation framework.

The good thing about Core Animation is that it provides smooth animations without burdening the CPU and slowing down your app. 

Download the starter project here and launch it. I am using Xcode 12.0 for this tutorial.

Run the app on the simulator and click on the button to show the next screen.

So far you are using the default transition implemented with the modal presentation.

Open the ViewController.swift file and change the showMenu action method code to the following:

let menuViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MenuViewController")
// 1
menuViewController.modalPresentationStyle = .fullScreen
// 2
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
transition.type = .push
transition.subtype = .fromBottom
// 3
view.window?.layer.add(transition, forKey: kCATransition)
present(menuViewController, animated: false, completion: nil)

Let’s walk through the code above:

// 1: Here you want to make the called screen shown in full screen, since iOS 13 you need to explicitly set it since it’s no longer the default behavior.

// 2: Here you define and configure the transition behavior, the timing curve, the animation duration, its type and direction.

// 3: Finally you assign the transition to the window handling the view and present the menu view controller as you would do without transition.

Build and run, click the button and notice how the menu screen is pushed from the top to the bottom.

Add transition to the dismiss action

Now close the menu screen by clicking the button at the top left, notice how the screen is dismissed with an animation from top to bottom, this is actually the default animation as well which you gonna change now 🙂

Select the MenuViewController.swift file and change the code inside the dismiss action method to the following code:

let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
transition.type = .push
transition.subtype = .fromTop
self.view.window?.layer.add(transition, forKey: kCATransition)
self.dismiss(animated: true, completion: nil)

This is the same code you used to show the menu screen except that you changed the transition direction.

Build and run and experiment both transitions 😉

That’s it, here is the final project, you can also find it on Github here.

What type of custom transition do you prefer for your app screens navigation flow? Let me know in the comments below.

Malek
iOS developer with over than 11 years of extensive experience working on several projects with different sized startups and corporates.