View controller transitions with UIKit Dynamics – Part 1

There currently are several methods to implement custom transitions between view controllers, other than the standard modal and push / pop transition, well known since the first days of iOS. Most commonly, custom transitions involve using the UIViewControllerAnimatedTransitioning protocol. It enables to create interesting animations when view controllers appear on the screen, either automatically or following a user action.

During the transitions, the root views of the presenting and presented view controllers are animated objects. As any kind of UIView, they are able to perform animations created either with the Core Animation framework, Auto Layout or UIKit Dynamics. In the first part of this article we use UIKit Dynamics to animate the transitions between view controllers that are added on the fly to a view controller container. In the second part of the article, we also use UIKit Dynamics in association with an interactive transition to add an interesting effect at the end of the transition between two view controllers.

If you need a better understanding of the what UIKit Dynamics is and how it can be used in your application, you can read my previous blog post on this topic. It explains the basic theory behind the framework and this article builds upon that with another practical application of the dynamic animations in the context of the view controller custom transitions.

What are we going to build ?

This article is structured around a simple example of implementing an animated transition between two view controllers using a pan gesture to slide up the top view controller, revealing the view controller underneath. This animation is similar to the iPhone lock screen which reveals the camera app screen when the user drags up the camera button.

view controllers transition using UIKit Dynamics

The Xcode project is available for download here.

The animations created using UIKit Dynamics depend on the amplitude of the pan gesture:

  • if distance of the pan gesture is smaller than one third of the screen height, the top view controller falls back down and hits the bottom with a small bounce.
  • if the pan gesture exceeds one third of the screen height, the top view controller continues to slide up until it completely disappears.

The second view controller located below the animated view controller is visible as soon as the animation starts. When the top view controller exits the screen, the second view controller becomes the top one and the animation can be played in a loop. The two view controllers are differentiated by they background color and a label indicating which is at the top and which is at the bottom.

Replaceable view controller

The animated view controllers are instances of a very simple UIViewController subclass containing only a UILabel.

The most important thing about this custom controller class is that its main view ignores user interactions so that the pan gesture is recognized by the container view controller. All the code for the replaceable view controller is in the -viewDidLoad method:

Container view controller

The container view controller is another UIViewController subclass incorporating all the interesting code. This view controller’s role is to present the replaceable view controllers and handle the pan gesture that drives the animation.

Inserting the replaceable view controllers

The replaceable view controllers are created on the fly and added to the container. The top one is added when the application is launched and the bottom view controller is inserted below each time a pan gesture is detected:

Using the dynamic behaviors

The animations are created exclusively using dynamic behaviors. This means the container view controller holds a strong pointer to a UIDynamicAnimator, to which we add and remove behaviors attached to the main view of the replaceable view controller at the top.

The behaviors we use are:

  • UIAttachmentBehavior: to move the top view in sync with the pan gesture, we attach it to the touch location on the screen
  • UIGravityBehavior: when the gesture is finished, the gravity behavior either makes the view fall back down or pulls it through the top of the screen, by changing the direction of the force.
  • UICollisionBehavior: to stop the view from falling through the bottom of the screen when the gravity is oriented down
  • UIDynamicItem: when the pan gesture is finished, we apply its velocity to the view to give it an additional impulse which, if it’s strong enough, makes the view disappear through the top

We also use an action block on the collision behavior to detect when the top view is completely off screen and remove it from the view hierarchy as well as its parent view controller from the container:

Playing the animations in the gesture handler

We’re using a screen edge gesture recognizer which only detects the pan gestures initiated at the bottom edge. This type of gestures was introduced in iOS7 to create more user interactions opportunities.

The problem with the bottom edge gesture recognizer is that it’s used by the system to slide up the Control Center interface. To limit the interference between the custom and the standard bottom gesture recognizer, we have to hide the status bar by overriding the -prefersStatusBarHidden method and returning YES (I know, it’s strange having to do that).

The dynamic behaviors are attached and removed from the main view of the top view controller depending on the gesture state:

  • when the gesture begins, the attachment behavior is created and associated to the top view. At the same time, a new replaceable view controller is inserted below the top one.
  • when the gesture is in progress, the attachement behavior anchor point follows the position of the touch on the screen. The movement of the view is constrained vertically by using a constant x coordinate for the anchor point.
  • when the gesture is finished or cancelled, the gravity, collision and dynamic item behaviors are added to the top view, and the attachment behavior is removed from the animator. There are two possibilities:
    • the touch position is smaller than one third of the screen height: the gravity orientation is top-down.
    • the touch position is greater than one third of the screen height: the gravity orientation is bottom-up and we apply the gesture velocity to the view

Conclusion

As demonstrated in this blog post and the previous one, UIKit Dynamics is a very versatile set of classes that can be used in very different contexts: to animate the subviews of a view controller, but also to create interesting transitions between two view controllers.

Before iOS8 and the large screen devices, I didn’t use the container view controllers a lot in the iPhone applications, but they came in handy in a few specific use cases for the iPad. On the small screen devices, I prefer using the animated and interaction transitioning protocols, and we’ll see in the next blog post how to use UIKit Dynamics with an interactive transition.

 

Catalin Rosioru

 

One thought on “View controller transitions with UIKit Dynamics – Part 1

Comments are closed.