iOS (Swift) — Custom Transitions
Tags: swift, ios, mobile, uikit
Published: 2023-01-02 18:45:28

While developing multiple apps through my years as an iOS developer, I was requested more than once to make a different custom transition between screens than what the iOS system default transitions have to offer.

In this article, I’ll show the basic transition the iOS system gives us, and how to create your own custom transition when moving between `UIViewController`.

## Default transition
Imagine the following scenario, we have a button on the screen, when the user taps the button another screen with full-screen red background shows up.
The red background `UIViewController` will cover the current `UIViewController` from bottom to top, this is the default iOS transition and it’s called `.coverVertical`.

To present a `UIViewController` from another `UIViewController` we can use the following code:

```
let redViewController = UIStoryboard(name: "Main", bundle: nil)
                        .instantiateViewController(identifier: "redViewController")
redViewController.modalPresentationStyle = .fullScreen
self.present(redViewController, animated: true)
```

As mention before let us see all the transitions options the iOS system give us:

- `.coverVertical` — this is the default behavior the iOS system gives us, the presented `UIViewController` covers the presenting `UIViewController` from bottom to top.
- `.flipHorizontal` — flips the presenting `UIViewController` horizontally and presenting the new `UIViewController` on the other side.
- `.crossDissolve` — fades the presenting `UIViewController` to the presented `UIViewController`.
- `.partialCurl` — flips the presenting `UIViewController` to the presented UIViewController from bottom to top like a page in a book.
An example of how to use a different iOS default transition than `coverVertical`:

```
func openRedViewController() {
  let redViewController = UIStoryboard(name: "Main", bundle: nil)
                          .instantiateViewController(identifier: "redViewController")
  redViewController.modalPresentationStyle = .fullScreen
  redViewController.modalTransitionStyle = .partialCurl
  self.present(redViewController, animated: true)
}
```
We’ve added the `.modalTransitionStyle` to our `UIViewController` and set its property to `.partialCurl`, so now we don't get `coverVertical` transition but `paritalCurl` instead.

Those four transitions are the basic transitions the iOS system gives us, but what if we wanted more? What if we want a different transition? What if we want to control the velocity, timing, alignment, and more? How can we do that?

The following code shows us how to create a “push” transition from right to left:

```
func createPushRightToLeftTransition() -> CATransition {
  let transition: CATransition = CATransition()
  transition.startProgress = 0.0
  transition.endProgress = 1.0
  transition.type = .push
  transition.subtype = .fromRight
  transition.duration = 0.3
  return transition
}
```
Firstly we create an object of type CATransition this object will contain all the properties we need to achieve the transition we want:

- `startProgress` — Indicates the start point of the receiver as a fraction of the entire transition.
endProgress — Indicates the endpoint of the receiver as a fraction of the entire transition.
- `type — the name of the transition, multiple options we have here:
fade, moveIn, push and reveal.
Default `isfade`.
- `subtype` — An optional subtype for the transition. used to specify the transition direction for motion-based transitions, values: `fromLeft`, `fromRight`, `fromTop`, `fromBottom`.
- `duration` — The basic duration of the transition. (seconds)
We just created our transition object, but how do we use it? Let’s take a look at the following code:

`
func openRedViewController() {
  let redViewController = UIStoryboard(name: "Main", bundle: nil)
                          .instantiateViewController(identifier: "redViewController")
  let transition = createPushRightToLeftTransition()
  self.view.window?.layer.add(transition, forKey: "kCATransition")
  self.present(redViewController, animated: false)
}
```


Again, as we have seen before we are creating our `redViewController` object, but there are two main changes here so we can use our custom transition.

- We added a new line, on the view.window` where we add to its layer our custom transition.
when we call `self.present` we have to set the animated parameter to false.
- Those two conditions will allow us to use our custom transition, once we call this function the `redViewController` will be pushed from right to left in 0.3 seconds.

Let’s see another example of a custom transition, this time we are going to create a fade transition, where the presenting `UIViewController` fade out and the presented `UIViewController` fades in:
```
func createFadeTransition() -> CATransition {
  let transition: CATransition = CATransition()
  transition.type = .fade
  transition.duration = 0.75
  return transition
}
```
As we did before, we create our `CATransition` object, but this time we use fade as our type for the transition, we then set the duration to 0.75 seconds.

As same as we did before with presenting a `UIViewController` with a custom transition, we can do the same when want to dismiss a `UIViewController`, take a look at the following code snippet:
```
func dismissViewController() {
  let transition = createFadeTransition()
  self.view.window?.layer.add(transition, forKey: "kCATransition")
  self.dismiss(animated: false, completion: nil)
}
```
Important to remember here is to set the animated property for the dismiss function to false otherwise, our custom transition will not work.

## Conclusion
CATransition object is great to create different and custom transitions. we have a variety of types and subtypes with can use to create many custom transitions, we can also set the duration of the transition, the start point, and the endpoint.
For more reading about custom transitions please click [here](https://developer.apple.com/documentation/quartzcore/catransition).