UIKit Dynamics Tutorial
Learn how to make your user interfaces in iOS 7 feel realistic with this UIKit Dynamics tutorial! By Colin Eberhardt.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
UIKit Dynamics Tutorial
25 mins
Note from Ray: This is an abbreviated version of a chapter from iOS 7 by Tutorials that we are releasing as part of the iOS 7 Feast. We hope you enjoy!
Update note: Interested in Swift? Check out the version of this tutorial updated for Swift and iOS 8!
You have probably come to realize that iOS 7 is something of a paradox; while you’re being encouraged to do away with real-world metaphors and skeuomorphism, Apple encourages you at the same time to create user interfaces that feel real.
What does this mean in practice? The design goals of iOS 7 encourage you to create digital interfaces that react to touch, gestures, and changes in orientation as if they were physical objects far beyond a simple collection of pixels. The end result gives the user a deeper connection with the interface than is possible through skin-deep skeuomorphism.
This sounds like a daunting task, as it is much easier to make a digital interface look real, than it is to make it feel real. However, you have some nifty new tools on your side: UIKit Dynamics and Motion Effects.
- UIKit Dynamics is a full physics engine integrated into UIKit. It allows you to create interfaces that feel real by adding behaviors such as gravity, attachments (springs) and forces. You define the physical traits that you would like your interface elements to adopt, and the dynamics engine takes care of the rest.
- Motion Effects allows you to create cool parallax effects like you see when you tilt the iOS 7 home screen. Basically you can harness the data supplied by the phone’s accelerometer in order to create interfaces that react to changes in phone orientation.
When used together, motion and dynamics form a powerhouse of user experience tools that make your digital interfaces come to life. Your users will connect with your app at a deeper level by seeing it respond to their actions in a natural, dynamic way.
Getting started
UIKit dynamics can be a lot of fun; the best way to start learning about them is to jump in feet-first with some small examples.
Open Xcode, select File / New / Project … then select iOS\Application\Single View Application and name your project DynamicsPlayground. Once the project has been created, open ViewController.m and add the following code to the end of viewDidLoad
:
UIView* square = [[UIView alloc] initWithFrame:
CGRectMake(100, 100, 100, 100)];
square.backgroundColor = [UIColor grayColor];
[self.view addSubview:square];
The above code simply adds a square UIView
to the interface.
Build and run your app, and you’ll see a lonely square sitting on your screen, as shown below:
If you’re running your app on a physical device, try tilting your phone, turning it upside-down, or even shaking it. What happens? Nothing? That’s right — everything is working as designed. When you add a view to your interface you expect it to remain firmly stuck in place as defined by its frame — until you add some dynamic realism to your interface!
Adding gravity
Still working in ViewController.m, add the following instance variables:
UIDynamicAnimator* _animator;
UIGravityBehavior* _gravity;
Add the following to the end of viewDidLoad
:
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
_gravity = [[UIGravityBehavior alloc] initWithItems:@[square]];
[_animator addBehavior:_gravity];
I’ll explain this in a moment. For now, build and run your application. You should see your square slowly start to accelerate in a downward motion until it drops off the bottom of the screen, as so:
In the code you just added, there are a couple of dynamics classes at play here:
-
UIDynamicAnimator
is the UIKit physics engine. This class keeps track of the various behaviors that you add to the engine, such as gravity, and provides the overall context. When you create an instance of an animator, you pass in a reference view that the animator uses to define its coordinate system. -
UIGravityBehavior
models the behavior of gravity and exerts forces on one or more items, allowing you to model physical interactions. When you create an instance of a behavior, you associate it with a set of items — typically views. This way you can select which items are influenced by the behavior, in this case which items the gravitational forces affect.
Most behaviors have a number of configuration properties; for example, the gravity behavior allows you to change its angle and magnitude. Try modifying these properties to make your objects fall up, sideways, or diagonally with varying rates of acceleration.
NOTE: A quick word on units: in the physical world, gravity (g) is expressed in meters per second squared and is approximately equal to 9.8 m/s2. Using Newton’s second law, you can compute how far an object will fall under gravity’s influence with the following formula:
distance = 0.5 × g × time2
In UIKit Dynamics, the formula is the same but the units are different. Rather than meters, you work with units of thousands of pixels per second squared. Using Newton’s second law you can still work out exactly where your view will be at any time based on the gravity components you supply.
Do you really need to know all this? Not really; all you really need to know is that a bigger value for g means things will fall faster, but it never hurts to understand the math underneath.
Setting boundaries
Although you can’t see it, the square continues to fall even after it disappears off the bottom of your screen. In order to keep it within the bounds of the screen you need to define a boundary.
Add another instance variable in ViewController.m:
UICollisionBehavior* _collision;
Add these lines to the bottom of viewDidLoad
:
_collision = [[UICollisionBehavior alloc]
initWithItems:@[square]];
_collision.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:_collision];
The above code creates a collision behavior, which defines one or more boundaries with which the associated items interact.
Rather than explicitly adding boundary co-ordinates, the above code sets the translatesReferenceBoundsIntoBoundary
property to YES. This causes the boundary to use the bounds of the reference view supplied to the UIDynamicAnimator
.
Build and run; you’ll see the square collide with the bottom of the screen, bounce a little, then come to rest, as so:
That’s some pretty impressive behavior, especially when you consider just how little code you’ve added at this point.