Auto Layout and constraints animation

Animations are an essential aspect of iOS and have become increasingly important in its latest versions. Besides providing a fun and immersive user experience, they play a major role in highlighting through motion the important parts of the content and complement the static hierarchy of information.

There are multiple ways views can be animated in UIKit and I introduced some of them in the previous blog posts:

  • UIKit Dynamics, which use a physics simulation engine built in iOS
  • UIKit Motion Effects which use data from the device motion sensors to create animations like the parallax effect
  • Core Animation is the low level animation framework available in Cocoa and Cocoa Touch, which allows to create virtually any kind of animation applied to CALayer objects
  • UIView animations, which are a set of UIView class methods wrapped around Core Animation. Their main purpose is to simplify the process of animating the backing CALayer of the UIView without resorting to the use of the low level Core Animation API.

Animations that involve moving a view on the screen or changing its shape generally require to modify the frame of the view. If the view is displayed using Auto Layout, which sets the frame automatically, the animations create conflicts between the Auto Layout constraints and the size and position of the view.

There a several techniques to go around most of these issues, but in this article I will focus on explaining how to animate changes made directly to Auto Layout constraints.

Animate constraint modifications with UIView animations

Auto Layout uses constraints to determine the frames of views it draws on screen.

The constraints, which are instances of NSLayoutConstraint class, are defined using a multiplier and a constant which are applied to the attribute of the target item according to the formula:

targetAttribute = referenceAttribute x multiplier + constant

Constraints can be adjusted by changing the multiplier, constant or priority, and they can also be added or removed on the fly, in code. These modifications break the initial balance set by Auto Layout, which reacts by repositioning the views according to the new constraints. The transition between the initial and the final states can be animated by invoking the -layoutIfNeeded method from within the animations block of a UIView animation method.

As explained earlier, UIView animations are internally built using the Core Animation API. The animations are applied to the backing layer of the views that appear in the animations block.
When Auto Layout is used to place the view on screen, the animation consists in interpolating between the initial stable state, where all the constraints are satisfied, to the final state, which is also consistent. During the intermediate steps, the view’s constraints are not satisfied and the view is temporarily out of sync with Auto Layout.

Constraint animation by example

I have build a simple example to show how Auto Layout constraint animation works; the goal was to progressively reveal a UIView by increasing its height from zero to the final size as determined by Auto Layout:

auto layout constraint animation

The sample project is available for download on GitHub.

To be able to use this animation with any kind of content view, I have created a UIView subclass called PopupView which has a simple view hierarchy rendered exclusively by Auto Layout:

view hierarchy for the popup view

The hierarchy is built just before displaying the popup view on screen by adding each subview to its parent view:

The initial constraints are set up in the -updateConstraints methods. They basically establish the relationships between each parent view and its child subview:

The animation is created in two steps using UIView animation methods. The first layout pass in needed to set up the initial state of the view hierarchy; at this stage, the content view height is zero. The second layout pass creates the actual animation between the zero height and the real height of the content view as returned by its -intrinsicContentSize method:

Conclusion

As demonstrated in the previous example, it is very easy to create animations by modifying the constraints and using UIView animations to interpolate between the old and the new constraints.
It is technically possible to use this method and animate changes between complex view layouts, but the more complicated the view hierarchy, the more constraints we have to update simultaneously and it isn’t easy to keep track of each of them and create realistic animations at the same time.

 

Catalin Rosioru