UIKit Dynamics overview

Introduction

UIKit Dynamics was introduced in iOS7 as part of the general trend of replacing the skeuomorphic elements in user interface design by more subtle, motion based effects.

Dynamics is a set of UIKit APIs that operate as an internal physics engine and emulate real world 2D animation behaviors applied to the elements visible on the screen. It is part of the same family as UIMotionEffect and should be used as another tool for creating interesting animations in addition to the constantly improving UIView animations and the Core Animation framework.

How UIKit handles the physics animations

The dynamics API consists of several classes organized in a simple hierarchy defining the mechanics of the system.

UIDynamicItem protocol

UIDynamicItem is a simple protocol that custom object have to conform to be able to perform the dynamic animations.

Apple provides two UIKit classes that conform to this protocol and serve 99% of the dynamic animation use cases: UIView and UICollectionViewLayoutAttributes.

A custom class that conforms to UIDynamicItem protocol should expose these properties:

  • bounds: CGRect defining the size of the dynamic item
  • center: CGPoint defining the position of the dynamic item in the superview coordinate system
  • transform: CGAffineTransform defining the rotation of the dynamic item (CGAffineTransform is able to specify other types of 2D transformations, but only the rotation is supported by UIKit Dynamics)

UIDynamicBehavior class

UIDynamicBehavior is generally derived and used as a container for several specific animation behaviors that operate simultaneously on one or more UIDynamicItems.

The class defines an action attribute, which is a block of code that’s executed at each step of the animation. If you use the action block, you should make sure it executes as quickly as possible to keep the animation running smoothly.

The method -addChildBehavior: is used to group inside the same UIDynamicBehavior object several other behaviors that run synchronously.

There are several dynamic behavior classes in UIKit, each focusing on specific physical interactions:

  • UIGravityBehavior: applies a constant force to the dynamic item. We can specify the magnitude and the direction of the force (it can be other than vertical).
  • UICollisionBehavior: defines how two dynamic items react when theirs bounds touch each other, or when an item touches a predefined, invisible boundary. It’s possible to register as the collision behavior delegate and add custom actions when before and after a collision occurs.
  • UIAttachmentBehavior: creates an invisible attachment between the dynamic item and a point in the reference view (generally, the superview) or a point in another dynamic item. The bond can be rigid or elastic (acting like a spring) depending on the values of the properties dumping and frequency.
  • UIPushBehavior: applies a force to a dynamic item, defined by an angle and a magnitude. The difference with respect to the UIGravityBehavior is that the former can be applied to any point of the item, while the gravity only applies to its center. The force can be exerted in two different ways (defined by the mode property):
    • instantaneously: the item immediately reaches the maximum speed, then it slows down (if there is a resistance)
    • continuously: the force is applied without interruption until the item is removed from the behavior or the behavior is removed from the animator.
  • UISnapBehavior: moves vigorously a dynamic item to a specific point in the reference view. The springy effect can be moderated by changing the value of the damping property
  • UIDynamicItemBehavior: specifies some physical properties of the dynamic item that have an influence on the other behaviors attached to the same item. The properties that can be altered using an instance of this class are density, resistance, angularResistance, friction, elasticity (read more about the meaning of each property in Apple’s documentation).

UIDynamicAnimator class

The animator is the element that actually sets the dynamic items in motion and each step of animation according to their attached behaviors.

The UIDynamicAnimator acts like a controller between the internal physics engine and the items position and rotation on the screen. An animator object is attached either to a reference view (usually the view containing the animated items) or a collection view layout, transforming it into a scene where the dynamic animations are performed.

The animations start as soon as the dynamic behaviors are added to the animator using its -addBehavior: method. They stop either when the behaviors are removed from the animator, or when the dynamic items “naturally” come to rest (when all forces cancel each other and the item find their equilibrium).

A pointer to the dynamic animator should be held strongly by the custom object that uses it. Often, the custom view controller contains a strong property pointing to the animator.

Dynamic animations don’t work very well in conjunction with the other types of animation, because multiple animations may act on the same property of the object, the most problematic being the frame. If you don’t want to create conflicts , it’s better to remove the animated views from any other kind of manual (Core Animation, UIView animation) or automatic animation (Auto Layout should be disabled on the animator reference view, for example).

As usual, the best way to understand how the dynamic effects work is to see them in action. You can download on GitHub the sample project that illustrates the two examples below.

Example 1: bouncing ball

As with other types of animation, the classic bouncing ball example is pretty easy to implement using UIKit Dynamics.

Generally, any interesting effect is obtained by overlaying several behaviors on the same animated item. You have to deconstruct the animation as you imagined it into several individual behaviors; sometimes different behavior combinations may lead to very similar effects.

In this example, we’re using UIGravityBehavior to make the ball (UIVIew instance) fall from the top of the screen, the UICollisionBehavior to make the ball hit an imaginary boundary at the top of another fixed view, and the UIDynamicItemBehavior to add elasticity to the ball and make it bounce when it collides.

We also use the collision delegate methods to change the background color of the base view each time it is hit by the ball.

Example 2: attached views

I call this example “attached views” because the animated views are attached with strings to the fixed view in the center of the screen:

attached views with uikit dynamics animator

The effect is obtained using one UISnapBehavior for each animated view, and adjusting the resistance to the snapping force using a UIDynamicItemBehavior for all views.

We’re also encapsulating all the behaviors in a UIDynamicBehavior subclass. The animated view are revealed or hidden simply by replacing the previous snap behaviors with new ones attached to other points in the reference view. These points are calculated in relation to the center of the fixed view. In the hidden position, the snapping points are equal to the center of the fixed view and the animated views hide behind the fixed view. In the visible position, the snapping points are the four corners of a square with the center equal to the center of the fixed view.

The strings that attach the animated views to the central fixed view are drawn using UIBezierPaths. Because the drawing occurs in the -drawRect: method, we create a custom UIView subclass which becomes the root view of the view controller (and the animator reference view), then override the -drawRect: method to draw the paths:

Finally, we have to call the -drawRect method at each step of the animation to update (recreate) the bezier path. We do this by assigning a block to the action property of our custom UIDynamicBehavior object and calling in this block the -setNeedsDisplay method on the root view.

Conclusion

This was just an overview of what is possible to create using UIKit Dynamics. The possibilities are really endless and it’s easy to go overboard with the dynamic visual effects. As with any kind of animation, it’s better to keep the effects subtle and not multiplying them unnecessarily.

 

Catalin Rosioru

 

2 thoughts on “UIKit Dynamics overview

Comments are closed.