iOS7 Series – UIKit Dynamics

 

Incorporating UIKitDynamics into your app is pretty simple!  The great thing about it is that you really get the most bang for your buck because the end result has a really big WOW Factor which is certain to impress your users.  Let’s take a quick conceptual drive around UIKitDynamics.

First we adopt the protocol into the ViewController which will implement UIKitDynamics, why?  Well because the objects which will be animated in the end will have to send back a lot of signals like “Hey, I collided with a boundary” or “hey I just hit somebody else and I was going this fast, in this direction”.  In order to receive these messages we use a delegate and its callbacks.

@interface … <UICollisionBehaviorDelegate>

We would need to create the view to animate and the property to reference a UIDynamicAnimator, which is the object in charge of handling animations in UIKitDynamics.

@property (nonatomic, weak) IBOutlet UIView *square1;

@property (nonatomic) UIDynamicAnimator* animator;

Basically we would prep all we need in viewDidLoad, such as instantiating an animator to call the shots inside a particular reference view.  Then we create a behavior or set of behaviors we wish to assign to our animatable view.  We define boundaries so we can keep our objects inside a view.  Finally we add the behaviors to the animator and set the viewcontroller as the delegate as well as set that animator object to our property in order to hold a reference to it.

That’s it!  Now we just sit back and get messages from the animator and the animated view via the callbacks.

– (void)viewDidLoad{

[super viewDidLoad];

UIDynamicAnimator* animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

UIGravityBehavior* gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:@[self.square1]];

UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.square1]];

collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;

[animator addBehavior:gravityBeahvior];

[animator addBehavior:collisionBehavior];

collisionBehavior.collisionDelegate = self;

self.animator = animator;

}

-(void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier atPoint:(CGPoint)p{

// Lighten the background color when the view is in contact with a boundary.

[(UIView*)item setBackgroundColor:[UIColor lightGrayColor]];

}

-(void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier{

// Restore the default color when ending a contcact.

[(UIView*)item setBackgroundColor:[UIColor grayColor]];

}

Ok so let’s use it in a simple example.  Let’s say we are building a Restaurant rating app.  It’s a single view app with a plain vanilla UIViewController which has these properties connected to those outlets:

@property (nonatomic, strong) IBOutlet UILabel *restaurantName;

@property (nonatomic, strong) IBOutlet UILabel *restaurantAddress;

//STAR RATING

@property (nonatomic, strong) IBOutlet UIImageView *stars1;

@property (nonatomic, strong) IBOutlet UIImageView *stars2;

@property (nonatomic, strong) IBOutlet UIImageView *stars3;

@property (nonatomic, strong) IBOutlet UIImageView *stars4;

@property (nonatomic, strong) IBOutlet UIImageView *stars5;

 

First let’s create the animator that will handle the animation inside our viewDidLoad:

// Create animator

UIDynamicAnimator* animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

Now we add the views we want to animate to the behaviors we want to implement:

//Create behaviors

    UIGravityBehavior* gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:@[self.stars1,self.stars2, self.stars3, self.stars4,self.stars5]];

UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.stars1,self.stars2, self.stars3, self.stars4,self.stars5]];

UIDynamicItemBehavior* propertiesBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.stars1,self.stars2, self.stars3, self.stars4,self.stars5]];

propertiesBehavior.elasticity = 5;

Notice that the last behavior is actually created to modify certain physical properties of an object, in this case elasticity.  There are other properties we can modify in this manner.

We can also add specific boundaries but in many cases we will want to simply use the view’s edges as the natural boundaries, so we use this line:

    collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;

Finally we add the behaviors to the animator, set the delegate to self and reference our animator through its property:

[animator addBehavior:gravityBeahvior];

[animator addBehavior:collisionBehavior];

collisionBehavior.collisionDelegate = self;

self.animator = animator;

Finally just add the following delegate callbacks to decide what gets done when a collision occurs:

-(void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier atPoint:(CGPoint)p{

// Lighten the background color when the view is in contact with a boundary.

[(UIView*)item setBackgroundColor:[UIColor lightGrayColor]];

}

-(void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier{

// Restore the default color when ending a contcact.

[(UIView*)item setBackgroundColor:[UIColor grayColor]];

}

That’s it!  There are lots of neat effects you can use but don’t overdo it or your users will sue you for giving them vertigo! J

Leave a Reply