View controller transitions with UIKit Dynamics – Part 2

This article is a follow-up to the previous blog post and shows yet another way to implement animated view controller transitions using UIKit Dynamics.

Before iOS7, it wasn’t easy to create custom transitions between view controllers and, more often than not, developers limited themselves to using the classic push and modal presentations and their standard animations.

Apple introduced in iOS7 the UIViewControllerAnimatedTransitioning protocol, greatly simplifying the implementation of custom animations when navigating from one view controller to the next. In this article, I will not go in depth about this protocol and the custom transitions in general, I will leave this for a later post which will focus exclusively on the topic. Here my goal is to demonstrate the use of UIKit Dynamics animations in the context of custom transitions.

What are view controller animated transitions?

Even the most simple apps have several view controllers. At a given moment, there usually is only one view controller on screen and it can present another view controller either automatically or following a user action. When the new view controller is modal, we use the terms presenting and presented view controllers, and there are properties of the view control class exposing this bi-directional relationship (presentingViewController and presentedViewController).

When a view controller is replaced by another one on screen, the switch between their main views is animated. Apple provides a set of standard animations, the default one for a modal presentation being the slide-up, but the animated transitions allow us to implement custom shifting between the two views.

Limitations

Unsurprisingly, the custom view controller transitions have a very good support for the UIView based animations, but don’t work well with other kinds of animations, including UIKit Dynamics.

To be able to use dynamics, we have to improvise a little bit trying to get around some of these limitations.

Modal presentation with dynamic animations

UIKit Dynamics is a set of APIs made available in iOS7 allowing to easily implement physics based animations between views. If you need to overview some basics about these APIs, I encourage you to read an older blog post on the topic.

As usual, I will support the demonstration with a code sample available here for download. The app shows an example of modal presentation using interactive transitions with a small touch of dynamic animations:

uiviewcontroller transitioning animator with uikit dynamics bouncing effect

Because we cannot implement the actual transition using UIKit Dynamics, we use it at the end of the transition to add an interesting bouncing effect.

Defining the transitioning animator

As specified above, the class that handles the animation between the view controllers conforms to the UIViewControllerAnimatedTransitioning protocol and implements the -transitionDuration: and -animateTransition: methods. The second method defines the actual animation replacing the presenting view with the presented view.

To be able to participate in a custom transition, the main view controller container conforms to the UIViewControllerTransitioningDelegate protocol and implements the -animationControllerForPresentedController:presentingController:sourceController: method returning an instance of the custom class which implements the transitioning animation.

Implementing the transition animation

To make things a bit more interesting, the transition is triggered by a pan gesture starting at the left edge of the main view controller. The gesture reveals the secondary (presented) view controller underneath with a continuous animation depending on the distance traveled by the finger on the screen. Playing the custom animation in sync with the user gesture is a feature of the interactive transitioning protocol, a nice addition to the view controller custom animated transitioning.

The main view controller is embedded in a container view controller in the storyboard. The container is the presenting view controller acting as the transitioning delegate and it also provides the area where the dynamic animations occur. As such, it contains most of the transitioning and dynamic animation logic.

We start by adding the UIScreenEdgePanGestureRecognizer to the main view controller:

In the gesture handler, we enable each step of the animation depending on the state of the gesture:

  • when the pan gesture starts, we instantiate the interaction controller from the standard UIPercentDrivenInteractiveTransition class and we present the secondary view controller
  • we ask the transitioning animator linked to the interaction controller to update the screen using the custom animation which progresses in sync with the panning distance
  • if the panning distance doesn’t exceed 40% of the screen width, we cancel the presentation and the main view controller slides back. Otherwise, the presentation is completed and the secondary view controller takes the full screen while the presenting view controller disappears through the right side.

Triggering the bouncing effect

The bouncing effect only applies to the main view controller either when the presentation is canceled (the user doesn’t slide the left edge far enough) or when the presented view controller is dismissed.

The effect is created using several dynamic behaviors:

  • push behavior: triggered when the transition is finished, it gives an impulse so the main view moves to the right. This mimics an elastic collision with the left edge of the screen.
  • gravity behavior: directed from right to left, it compensates the pushing force and makes the main view fall back to the left edge.
  • collision behavior: preventing the main view from falling out of the screen under the gravity, by adding a boundary to the left edge.

The dynamic animator enters the scene when the transition completed or canceled. It takes over from the transitioning animation, adding the final effect. Because the transitioning animator has to trigger the bouncing effect when the transition is actually finished, it asks the main view controller to enable the dynamic animation through its delegate:

The delegate method simply adds the collision behavior to the dynamic animator. Then we use the collision delegate methods to activate the push behavior when the first collision is detected, and to replace it by the gravity behavior when the main view starts moving to the right under the force of the impulse:

Conclusion

The same kind of effect could be implemented using only the transitioning animator with a lot less code.

UIKit Dynamics are not a very good application for view controller transitions, but this was an interesting experiment which also let me introduce the UIViewControllerAnimatedTransitioning and UIViewControllerInteractiveTransitioning protocols. I will give special attention to these two protocols in a future article because they enable us to implement engaging animations between view controllers.

 

Catalin Rosioru