Hackatron - UIKit Dynamics

Post on 15-Jan-2015

395 views 1 download

description

 

Transcript of Hackatron - UIKit Dynamics

Renzo G. PrettoiOS Developer

UIKit DynamicsLet the physics flow

Who’s talking

Who’s talking

About me

Renzo iOS DeveloperH-art!

#pragma mark founderrenzo.pretto@pragmamark.org!

@rgpretto

Chi siamoprogrammatori e imprenditori, ma soprattutto appassionati

Cosacreare una community di sviluppatori iOS e OS X

Perchésentivamo l’esigenza di condividere e confrontarci

Dovenel mondo virtuale, ma soprattutto nel mondo reale

Comeattraverso incontri periodici, eventi formativi e conferenze

Associazionedal Settembre siamo ufficialmente un’associazione culturale

Associazionedal Settembre siamo ufficialmente un’associazione culturale

Massimo

Giuseppe

RenzoMatteoFrancesco

Marco

Paolo

Stefano

Statuto

Statuto L’associazione senza fini di lucro #pragma mark ha lo

scopo di svolgere attività di “community of practice, ovvero di condivisione delle conoscenze ed esperienze tra persone

la cui professionalità ruota intorno le tecnologie informatiche e iOS in particolare, fornendo un nuovo

modello per connetterle nello spirito dell’apprendimento, della conoscenza condivisa e della collaborazione sia come

individui sia come gruppi”

152 partecipanti

16 speaker

15 sponsor

8 organizzatori

16 sessioni tecniche

10 ore di conferenza

2 track tematiche

20 gadget, licenze e coupon

Comunità

Ottobre 2013la comunità è cresciuta molto, oggi siamo in 150

Partecipantipiù di 300 persone hanno seguito i nostri eventi

Social205 iscritti al gruppo su facebook e 122 follower su twitter

Eventisvolti 9 eventi

DoveBrescia, Bergamo, Verona, Venezia, Milano

e presto a Treviso e Roma

follow us @pragmamarkorg

fb.com/groups/pragmamark/join to

subscribe on pragmamark.org

Today Agenda

• Introduction and core concepts

Today Agenda

• Introduction and core concepts

•Standard effects: dynamic behaviors

Today Agenda

• Introduction and core concepts

•Standard effects: dynamic behaviors

•Custom effects: custom behaviors

Today Agenda

• Introduction and core concepts

•Standard effects: dynamic behaviors

•Custom effects: custom behaviors

•Advanced concepts

Today Agenda

• Introduction and core concepts

•Standard effects: dynamic behaviors

•Custom effects: custom behaviors

•Advanced concepts

•UIDynamicItem

Today Agenda

• Introduction and core concepts

•Standard effects: dynamic behaviors

•Custom effects: custom behaviors

•Advanced concepts

•UIDynamicItem

•Collection View

Today Agenda

• Introduction and core concepts

•Standard effects: dynamic behaviors

•Custom effects: custom behaviors

•Advanced concepts

•UIDynamicItem

•Collection View

•Conclusion

UIKit Dynamics

UIKit Dynamics

UIKit Dynamics

Architecture

UIDynamicAnimator

Architecture

UIDynamicAnimator

UIDynamicBehavior UIDynamicBehaviorUIDynamicBehavior

Architecture

UIDynamicAnimator

UIDynamicBehavior UIDynamicBehaviorUIDynamicBehavior

Architecture

UIDynamicAnimator

UIDynamicBehavior UIDynamicBehavior

View

UIDynamicBehavior

Architecture

UIDynamicAnimator

UIDynamicBehavior UIDynamicBehavior

View View

UIDynamicBehavior

Architecture

UIDynamicAnimator

UIDynamicBehavior UIDynamicBehavior

View View View

UIDynamicBehavior

Architecture

UIDynamicAnimator Reference view

UIDynamicBehavior UIDynamicBehavior

View View View

UIDynamicBehavior

Architecture

UIDynamicAnimator Reference view

UIDynamicBehavior UIDynamicBehavior

View View View

UIDynamicBehavior

UIDynamicAnimator

UIDynamicAnimator

UIDynamicAnimator

•Define the coordinate systemUIDynamicAnimator

Reference view

UIDynamicAnimator

•Define the coordinate system

•Wraps underline engineUIDynamicAnimator

Reference view

UIDynamicAnimator

•Define the coordinate system

•Wraps underline engine

•Keeps track of all the associated behaviors

UIDynamicAnimator

Reference view

UIDynamicAnimator

•Define the coordinate system

•Wraps underline engine

•Keeps track of all the associated behaviors

•Run and optimize the animation

UIDynamicAnimator

Reference view

UIDynamicAnimator

•Define the coordinate system

•Wraps underline engine

•Keeps track of all the associated behaviors

•Run and optimize the animation

•Each dynamic animator is independent from other dynamic animators

UIDynamicAnimator

Reference view

UIDynamicAnimator

•Define the coordinate system

•Wraps underline engine

•Keeps track of all the associated behaviors

•Run and optimize the animation

•Each dynamic animator is independent from other dynamic animators

UIDynamicAnimator *dynamicAnimator; !dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; !dynamicAnimator.delegate = self; ... ![dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...

UIDynamicAnimator

Reference view

UIDynamicAnimator

•Define the coordinate system

•Wraps underline engine

•Keeps track of all the associated behaviors

•Run and optimize the animation

•Each dynamic animator is independent from other dynamic animators

UIDynamicAnimator *dynamicAnimator; !dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; !dynamicAnimator.delegate = self; ... ![dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...

UIDynamicAnimator

Reference view

UIDynamicAnimator

•Define the coordinate system

•Wraps underline engine

•Keeps track of all the associated behaviors

•Run and optimize the animation

•Each dynamic animator is independent from other dynamic animators

UIDynamicAnimator *dynamicAnimator; !dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; !dynamicAnimator.delegate = self; ... ![dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...

UIDynamicAnimator

Reference view

UIDynamicAnimator

•Define the coordinate system

•Wraps underline engine

•Keeps track of all the associated behaviors

•Run and optimize the animation

•Each dynamic animator is independent from other dynamic animators

UIDynamicAnimator *dynamicAnimator; !dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; !dynamicAnimator.delegate = self; ... ![dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...

UIDynamicAnimator

Reference view

UIDynamicAnimatorDelegate

@protocol UIDynamicAnimatorDelegate <NSObject> !@optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; !@end

UIDynamicAnimatorDelegate

•Notify pausing and resuming of UIKit Dynamic animator

@protocol UIDynamicAnimatorDelegate <NSObject> !@optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; !@end

UIDynamicBehaviour

UIDynamicBehavior

UIDynamicBehaviour

•Associated to UIDynamicAnimator

UIDynamicAnimator

UIDynamicBehavior

UIDynamicBehaviour

•Associated to UIDynamicAnimator•Add and remove behaviours to an animator at any times

UIDynamicAnimator

UIDynamicBehavior

UIDynamicBehaviour

•Associated to UIDynamicAnimator•Add and remove behaviours to an animator at any times•Usually associated to a view or a set of view

UIDynamicAnimator

UIDynamicBehavior

View View

UIDynamicBehaviour

•Associated to UIDynamicAnimator•Add and remove behaviours to an animator at any times•Usually associated to a view or a set of view•Composed

UIDynamicAnimator

UIDynamicBehavior

View View UIDynamicBehavior

View

UIDynamicBehaviour

•Associated to UIDynamicAnimator•Add and remove behaviours to an animator at any times•Usually associated to a view or a set of view•Composed•Can be subclassed

UIDynamicAnimator

UIDynamicBehavior

View View UIDynamicBehavior

View

Behaviors Common characteristics

• Initialised with items to animate

Behaviors Common characteristics

• Initialised with items to animate

• Items can be added to behavior at any times

Behaviors Common characteristics

• Initialised with items to animate

• Items can be added to behavior at any times

•Behaviour can be configured before or after add to an animator

Behaviors Common characteristics

• Initialised with items to animate

• Items can be added to behavior at any times

•Behaviour can be configured before or after add to an animator

•Behavior influence stops when behaviour is removed

Primitive behaviors

Default Behaviors

UIDynamicBehavior

Default Behaviors

UIDynamicBehavior

UIGravityBehavior•Gravity

Default Behaviors

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior•Collisions

•Gravity

Default Behaviors

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

•Collisions

•Gravity

•Attachments

Default Behaviors

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

•Collisions

•Gravity

•Attachments

•Snap

Default Behaviors

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

UIPushBehavior

•Collisions

•Gravity

•Attachments

•Snap

•Forces

Default Behaviors

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

UIPushBehavior

UIDynamicItemBehavior

•Collisions

•Gravity

•Attachments

•Snap

•Forces

• Item properties

UIGravityBehavior

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

UIPushBehavior

UIDynamicItemBehavior

UIGravityBehavior

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

UIPushBehavior

UIDynamicItemBehavior

UIGravityBehavior

@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end

UIGravityBehavior

@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end

UIGravityBehavior

@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end

UIGravityBehavior

@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end

UIGravityBehavior

@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end

UIGravityBehavior

UIGravityBehavior

•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;

UIGravityBehavior

•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;

or@property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;

UIGravityBehavior

•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;

or@property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;

•Default vector is (0.0, 1.0)(0.0, 1.0)

UIGravityBehavior

•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;

or@property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;

•Default vector is (0.0, 1.0)

•Magnitude 1.0 accelerate view to 1000 points/s2 (0.0, 1.0)

UIGravityBehavior

•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;

or@property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;

•Default vector is (0.0, 1.0)

•Magnitude 1.0 accelerate view to 1000 points/s2

•Can add and remove items at any time

(0.0, 1.0)

- (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;

UICollisionBehavior

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

UIPushBehavior

UIDynamicItemBehavior

UICollisionBehavior

UICollisionBehavior

@interface DPCollisionsViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; ! UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end

UICollisionBehavior

@interface DPCollisionsViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; ! UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end

UICollisionBehavior

@interface DPCollisionsViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; ! UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end

UICollisionBehavior

@interface DPCollisionsViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; ! UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end

UICollisionBehavior

@interface DPCollisionsViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; ! UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end

UICollisionBehavior

@interface DPCollisionsViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; ! UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end

UICollisionBehavior

@interface DPCollisionsViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPGravityCollisionViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UICollisionBehavior *collisionBehavior; collisionBehavior = [[UICollisionBehavior alloc] initWithItems:items]; collisionBehavior.translatesReferenceBoundsIntoBoundary = YES; collisionBehavior.collisionDelegate = self; ! UIGravityBehavior *gravityBehavior; gravityBehavior =[[UIGravityBehavior alloc] initWithItems:items]; [self.animator addBehavior:collisionBehavior]; [self.animator addBehavior:gravityBehavior]; } ... @end

Collision Boundaries

•Can specify different boundaries

Collision Boundaries

•Can specify different boundaries•Reference view

@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

Collision Boundaries

•Can specify different boundaries•Reference view

@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

Collision Boundaries

•Can specify different boundaries•Reference view

@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

•Segmentes- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;

Collision Boundaries

•Can specify different boundaries•Reference view

@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

•Segmentes- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;

•Bezier paths (approximated)- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath;

Collision Boundaries

•Can specify different boundaries•Reference view

@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

•Segmentes- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;

•Bezier paths (approximated)- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath;

Collision Boundaries

•Can specify different boundaries•Reference view

@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;

• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;

•Segmentes- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;

•Bezier paths (approximated)- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath;

•Boundaries don't have an existence on screen

Collision Mode

•Property collisionmode

Collision Mode

•Property collisionmode@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;

Collision Mode

•Property collisionmode@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;

• UICollisionBehaviorModeBoundaries

Collision Mode

•Property collisionmode@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;

• UICollisionBehaviorModeBoundaries• UICollisionBehaviorModeItems

Collision Mode

•Property collisionmode@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;

• UICollisionBehaviorModeBoundaries• UICollisionBehaviorModeItems

• UICollisionBehaviorModeEverything (default)

Tips

•Can use multiple collision behaviors

Tips

•Can use multiple collision behaviors

•Add and remove items to this behaviour anytime - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;

Tips

•Can use multiple collision behaviors

•Add and remove items to this behaviour anytime

•Collision detection have CPU cost

- (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;

•Methods that inform collision start / end between view

UICollisionBehaviorDelegate

•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;

- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;

UICollisionBehaviorDelegate

•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;

- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;

•Methods that inform collision start /end between boundaries

UICollisionBehaviorDelegate

•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;

- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;

•Methods that inform collision start /end between boundaries- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p;

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

UICollisionBehaviorDelegate

•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;

- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;

•Methods that inform collision start /end between boundaries- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p;

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

UICollisionBehaviorDelegate

•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;

- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;

•Methods that inform collision start /end between boundaries- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p;

- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier;!•Reference view has nil identifier

UICollisionBehaviorDelegate

UIAttachmentBehavior

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

UIPushBehavior

UIDynamicItemBehavior

UIAttachmentBehavior

UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end

UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end

UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end

UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end

UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end

UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end

•View connected to an attachment point

UIAttachmentBehavior

•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;

UIAttachmentBehavior

•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;

•Two views connected together

UIAttachmentBehavior

•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;

•Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;

UIAttachmentBehavior

•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;

•Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;

•Specify connection point offset

UIAttachmentBehavior

•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;

•Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;

•Specify connection point offset - (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point;

UIAttachmentBehavior

•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;

•Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;

•Specify connection point offset - (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point;

- (instancetype)initWithItem:(id <UIDynamicItem>)item1 offsetFromCenter:(UIOffset)offset1 attachedToItem:(id <UIDynamicItem>)item2 offsetFromCenter:(UIOffset)offset2;

UIAttachmentBehavior

Springs

•Springs

Springs

•Springs @property (readwrite, nonatomic) CGFloat damping;

Springs

•Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;

Springs

•Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;

UISnapBehavior

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

UIPushBehavior

UIDynamicItemBehavior

UISnapBehavior

UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end

UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end

UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end

UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end

UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end

UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end

UISnapBehavior

•Snap view in place in non rotated state

UISnapBehavior

•Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;

UISnapBehavior

•Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;

•Customize the dumping effects

UISnapBehavior

•Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;

•Customize the dumping effects @property (nonatomic, assign) CGFloat damping;

UIPushBehavior

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

UIPushBehavior

UIDynamicItemBehavior

UIPushBehavior

~F = m ~a

UIPushBehavior

• , apply force to views: ~F = m ~a

UIPushBehavior

• , apply force to views: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

~F = m ~a

UIPushBehavior

• , apply force to views: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

•Force vector expressed in two way:

~F = m ~a

UIPushBehavior

• , apply force to views: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

•Force vector expressed in two way: @property (readwrite, nonatomic) CGVector pushDirection;

~F = m ~a

UIPushBehavior

• , apply force to views: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

•Force vector expressed in two way: @property (readwrite, nonatomic) CGVector pushDirection;

or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;

~F = m ~a

UIPushBehavior

UIPushBehavior

•Customize where apply this force in the view

UIPushBehavior

•Customize where apply this force in the view

UIPushBehavior

•Customize where apply this force in the view- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;

UIPushBehavior

•Customize where apply this force in the view- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;

UIPushBehavior

•Customize where apply this force in the view- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;

•Can add and remove items at any time

UIPushBehavior

•Customize where apply this force in the view- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;

•Can add and remove items at any time- (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;

UIPushBehavior

•Customize where apply this force in the view- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;

•Can add and remove items at any time- (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;

UIPushBehavior

•Customize where apply this force in the view- (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;

•Can add and remove items at any time- (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;

UIPushBehavior Mode

•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

UIPushBehavior Mode

•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous

UIPushBehavior Mode

•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous • force still be applied while behaviour is active

UIPushBehavior Mode

•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous • force still be applied while behaviour is active

• views accelerate

UIPushBehavior Mode

•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous • force still be applied while behaviour is active

• views accelerate

•UIPushBehaviorModeInstantaneous

UIPushBehavior Mode

•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous • force still be applied while behaviour is active

• views accelerate

•UIPushBehaviorModeInstantaneous• apply a very quick impulse

UIPushBehavior Mode

•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous • force still be applied while behaviour is active

• views accelerate

•UIPushBehaviorModeInstantaneous• apply a very quick impulse

• view immediately acquire velocity (no acceleration)

UIPushBehavior Mode

•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous • force still be applied while behaviour is active

• views accelerate

•UIPushBehaviorModeInstantaneous• apply a very quick impulse

• view immediately acquire velocity (no acceleration)

• automatically disable itself after applying it

UIPushBehavior Mode

•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;

• UIPushBehaviorModeContinuous • force still be applied while behaviour is active

• views accelerate

•UIPushBehaviorModeInstantaneous• apply a very quick impulse

• view immediately acquire velocity (no acceleration)

• automatically disable itself after applying it

• to re-enable: @property (nonatomic, readwrite) BOOL active;

Example: force comparison

~F = m ~a

~a =~F

m

Example: force comparison

~F = m ~a

~a =~F

m

Example: gravity comparison

Feel The Force!

Feel The Force!

•Gravity

Feel The Force!

•Gravity

• views accelerate with the same rate

Feel The Force!

•Gravity

• views accelerate with the same rate

•Push behavior in continuos mode

Feel The Force!

•Gravity

• views accelerate with the same rate

•Push behavior in continuos mode

• the smaller views accelerate more

Feel The Force!

•Gravity

• views accelerate with the same rate

•Push behavior in continuos mode

• the smaller views accelerate more

•Push behavior in instantaneous mode

Feel The Force!

•Gravity

• views accelerate with the same rate

•Push behavior in continuos mode

• the smaller views accelerate more

•Push behavior in instantaneous mode

• view acquire velocity and then the velocity doesn’t change

Feel The Force!

•Gravity

• views accelerate with the same rate

•Push behavior in continuos mode

• the smaller views accelerate more

•Push behavior in instantaneous mode

• view acquire velocity and then the velocity doesn’t change

• the smaller views acquire more velocity

Unit of Measure

•Real world: Newton

Unit of Measure

•Real world: Newton

• 1 Newton accelerate 1Kg at a rate of 1 m/s2

Unit of Measure

•Real world: Newton

• 1 Newton accelerate 1Kg at a rate of 1 m/s2

•UIKit:

•  magnitude of 1.0 accelerate 100x100 point view to 100 points/s2

Unit of Measure

•Real world: Newton

• 1 Newton accelerate 1Kg at a rate of 1 m/s2

•UIKit:

•  magnitude of 1.0 accelerate 100x100 point view to 100 points/s2

• “UIKit Newton”

UIDynamicItemBehavior

UIDynamicBehavior

UIGravityBehavior

UICollisionBehavior

UIAttachmentBehavior

UISnapBehavior

UIPushBehavior

UIDynamicItemBehavior

•Customize dynamics properties for items

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity;

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction;

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density;

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance;

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance;

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;

•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;

•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;

•Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;

•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;

•Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;

•Can add and remove items at any time

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;

•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;

•Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;

•Can add and remove items at any time

UIDynamicItemBehavior

•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;

•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;

•Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;

•Can add and remove items at any time

UIDynamicItemBehavior

Long Story Short

• Identify the type of dynamic items you want to animate

Long Story Short

• Identify the type of dynamic items you want to animate

•Define container or reference view

Long Story Short

• Identify the type of dynamic items you want to animate

•Define container or reference view

•Create the behaviours

Long Story Short

• Identify the type of dynamic items you want to animate

•Define container or reference view

•Create the behaviours

•Add items to behaviours

Long Story Short

• Identify the type of dynamic items you want to animate

•Define container or reference view

•Create the behaviours

•Add items to behaviours

•Configure, add or remove behaviors to an animator

Custom behaviors

Custom Behavior

•Can subclass UIDynamicBehavior

Custom Behavior

•Can subclass UIDynamicBehavior

• add child behavior - (void)addChildBehavior:(UIDynamicBehavior *)behavior; - (void)removeChildBehavior:(UIDynamicBehavior *)behavior;

@property (nonatomic, readonly, copy) NSArray* childBehaviors;

Custom Behavior

•Can subclass UIDynamicBehavior

• add child behavior - (void)addChildBehavior:(UIDynamicBehavior *)behavior; - (void)removeChildBehavior:(UIDynamicBehavior *)behavior;

@property (nonatomic, readonly, copy) NSArray* childBehaviors;

•No CPU cost or any runtime difference

Example: gravity & collision

Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end

Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end

Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end

Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end

Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end

@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end

Example: gravity & collision

@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end

Example: gravity & collision

@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end

Example: gravity & collision

@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end

Example: gravity & collision

@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end

Example: gravity & collision

@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end

Example: gravity & collision

@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end

Example: gravity & collision

@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end

Example: gravity & collision

@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end

Example: gravity & collision

Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; !!!!!! ! } !@end

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll];

Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; !!!!!! ! } !@end

DPGravityCollisionBehavior *gravityAndCollision; gravityAndCollision= [[DPGravityCollisionBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityAndCollision];

Action Block

•Can define per-step actions

Action Block

•Can define per-step actions @property (nonatomic, copy) void (^action)(void);

Action Block

•Can define per-step actions @property (nonatomic, copy) void (^action)(void);

• UIDynamicAnimator invoke this block in each simulation step

Action Block

•Can define per-step actions @property (nonatomic, copy) void (^action)(void);

• UIDynamicAnimator invoke this block in each simulation step

•So performance are crucial

UIDynamicItem protocol

UIDynamicItem Protocol@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end

UIDynamicItem Protocol

•All items animated by UIKit Dynamics must implement this protocol

@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end

UIDynamicItem Protocol

•All items animated by UIKit Dynamics must implement this protocol

•Describe what UIKit Dynamics needs to animate an item

@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end

UIDynamicItem Protocol

•All items animated by UIKit Dynamics must implement this protocol

•Describe what UIKit Dynamics needs to animate an item

•position: center

@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end

UIDynamicItem Protocol

•All items animated by UIKit Dynamics must implement this protocol

•Describe what UIKit Dynamics needs to animate an item

•position: center

• size: bounds

@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end

UIDynamicItem Protocol

•All items animated by UIKit Dynamics must implement this protocol

•Describe what UIKit Dynamics needs to animate an item

•position: center

• size: bounds

• angle: transform (only 2D-transform)

@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end

UIDynamicItem Protocol

• center, bounds, and transform are read only once by UIKit

UIDynamicItem Protocol

• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time

UIDynamicItem Protocol

• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time

• center and transform are set on every animation tick

UIDynamicItem Protocol

• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time

• center and transform are set on every animation tick • methods performances are critical

UIDynamicItem Protocol

• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time

• center and transform are set on every animation tick • methods performances are critical

•After grab the initial state every external change to center, bounds, and transform will be ignored

UIDynamicItem Protocol

• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time

• center and transform are set on every animation tick • methods performances are critical

•After grab the initial state every external change to center, bounds, and transform will be ignored

•A dynamic item should always have a valid initial state

UIDynamicItem Protocol

• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time

• center and transform are set on every animation tick • methods performances are critical

•After grab the initial state every external change to center, bounds, and transform will be ignored

•A dynamic item should always have a valid initial state• need a size

UIDynamicItem Protocol

• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time

• center and transform are set on every animation tick • methods performances are critical

•After grab the initial state every external change to center, bounds, and transform will be ignored

•A dynamic item should always have a valid initial state• need a size

• need a reasonable position

UIDynamicItem Protocol

•All items animated by UIKit Dynamics must implement this protocol

UIDynamicItem Protocol

•All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol@interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... }

UIDynamicItem Protocol

•All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol@interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... }

• UICollectionViewLayoutAttributes conforms to protocol@interface UICollectionViewLayoutAttributes : NSObject < NSCopying, UIDynamicItem > { ... }

UIDynamicItem Protocol

•All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol@interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... }

• UICollectionViewLayoutAttributes conforms to protocol@interface UICollectionViewLayoutAttributes : NSObject < NSCopying, UIDynamicItem > { ... }

•Custom class can conform to protocol@interface DPDynamicObject : NSObject < UIDynamicItem > { ... }

Architecture

UIDynamicAnimator Reference view

UIDynamicBehavior UIDynamicBehavior

View View View

UIDynamicBehavior

Architecture

UIDynamicAnimator Reference view

UIDynamicBehavior UIDynamicBehaviorUIDynamicBehavior

NSObject"<UIDynamicItem>

NSObject"<UIDynamicItem>

NSObject"<UIDynamicItem>

@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end

Example 1: conform to UIDynamicItem

@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end

Example 1: conform to UIDynamicItem

@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end

Example 1: conform to UIDynamicItem

@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end

Example 1: conform to UIDynamicItem

@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end

Example 1: conform to UIDynamicItem

Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end

Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end

Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end

Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end

Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end

Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end

Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end

Example 1: conform to UIDynamicItem

Example 1: conform to UIDynamicItem

2013-10-17 18:58:05.598 DynamicsPlayground[771:60b] Animator is running 2013-10-17 18:58:05.609 DynamicsPlayground[771:60b] Center = {50, 50.04797} 2013-10-17 18:58:05.611 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.626 DynamicsPlayground[771:60b] Center = {50, 50.447464} 2013-10-17 18:58:05.629 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.642 DynamicsPlayground[771:60b] Center = {50, 51.054173} 2013-10-17 18:58:05.645 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.659 DynamicsPlayground[771:60b] Center = {50, 51.915657} 2013-10-17 18:58:05.661 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.675 DynamicsPlayground[771:60b] Center = {50, 53.031506} 2013-10-17 18:58:05.677 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] !... !2013-10-17 18:58:08.742 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.744 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.759 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.761 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.775 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.777 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.792 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.794 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.809 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.810 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.812 DynamicsPlayground[771:60b] Animator is stopped

Example 1: conform to UIDynamicItem

2013-10-17 18:58:05.598 DynamicsPlayground[771:60b] Animator is running 2013-10-17 18:58:05.609 DynamicsPlayground[771:60b] Center = {50, 50.04797} 2013-10-17 18:58:05.611 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.626 DynamicsPlayground[771:60b] Center = {50, 50.447464} 2013-10-17 18:58:05.629 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.642 DynamicsPlayground[771:60b] Center = {50, 51.054173} 2013-10-17 18:58:05.645 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.659 DynamicsPlayground[771:60b] Center = {50, 51.915657} 2013-10-17 18:58:05.661 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.675 DynamicsPlayground[771:60b] Center = {50, 53.031506} 2013-10-17 18:58:05.677 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] !... !2013-10-17 18:58:08.742 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.744 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.759 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.761 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.775 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.777 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.792 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.794 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.809 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.810 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.812 DynamicsPlayground[771:60b] Animator is stopped

•Can use a single dynamic item to animate different views

UIDynamicItem Use Case

•Can use a single dynamic item to animate different views

•Can map center or transform to something else

UIDynamicItem Use Case

•Can use a single dynamic item to animate different views

•Can map center or transform to something else

•To “animate” something that isnt’a a view or a collection view use a UIDynamicItem

UIDynamicItem Use Case

•Can use a single dynamic item to animate different views

•Can map center or transform to something else

•To “animate” something that isnt’a a view or a collection view use a UIDynamicItem

UIDynamicItem Use Case

Example 2: remap center property

Example 2: remap center property

@protocol ResizableDynamicItem <UIDynamicItem> !!@interface APLPositionToBoundsMapping : NSObject <UIDynamicItem> !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target; !@end !!@protocol ResizableDynamicItem <UIDynamicItem> !@property (nonatomic, readwrite) CGRect bounds; !@end

Example 2: remap center property

@protocol ResizableDynamicItem <UIDynamicItem> !!@interface APLPositionToBoundsMapping : NSObject <UIDynamicItem> !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target; !@end !!@protocol ResizableDynamicItem <UIDynamicItem> !@property (nonatomic, readwrite) CGRect bounds; !@end

Example 2: remap center property

@protocol ResizableDynamicItem <UIDynamicItem> !!@interface APLPositionToBoundsMapping : NSObject <UIDynamicItem> !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target; !@end !!@protocol ResizableDynamicItem <UIDynamicItem> !@property (nonatomic, readwrite) CGRect bounds; !@end

Example 2: remap center property#import "APLPositionToBoundsMapping.h" !@interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end !@implementation APLPositionToBoundsMapping !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } !- (CGRect)bounds { return self.target.bounds; // Pass through } !- (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } !- (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } !- (CGAffineTransform)transform { return self.target.transform; // Pass through } !- (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end

Example 2: remap center property#import "APLPositionToBoundsMapping.h" !@interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end !@implementation APLPositionToBoundsMapping !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } !- (CGRect)bounds { return self.target.bounds; // Pass through } !- (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } !- (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } !- (CGAffineTransform)transform { return self.target.transform; // Pass through } !- (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end

Example 2: remap center property#import "APLPositionToBoundsMapping.h" !@interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end !@implementation APLPositionToBoundsMapping !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } !- (CGRect)bounds { return self.target.bounds; // Pass through } !- (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } !- (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } !- (CGAffineTransform)transform { return self.target.transform; // Pass through } !- (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end

Example 2: remap center property#import "APLPositionToBoundsMapping.h" !@interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end !@implementation APLPositionToBoundsMapping !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } !- (CGRect)bounds { return self.target.bounds; // Pass through } !- (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } !- (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } !- (CGAffineTransform)transform { return self.target.transform; // Pass through } !- (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end

Example 2: remap center property@import UIKit; !!@interface APLCustomDynamicItemViewController : UIViewController @end !!@interface APLCustomDynamicItemViewController () @property (nonatomic, weak) IBOutlet UIButton *button1; @property (nonatomic, readwrite) CGRect button1Bounds; @property (nonatomic, strong) UIDynamicAnimator *animator; @end !!@implementation APLCustomDynamicItemViewController !- (void)viewDidLoad { ! // Save the button's initial bounds. self.button1Bounds = self.button1.bounds; // Force the button image to scale with its bounds. self.button1.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; self.button1.contentVerticalAlignment = UIControlContentHorizontalAlignmentFill; } !// ... continue !@end

Example 2: remap center property@import UIKit; !!@interface APLCustomDynamicItemViewController : UIViewController @end !!@interface APLCustomDynamicItemViewController () @property (nonatomic, weak) IBOutlet UIButton *button1; @property (nonatomic, readwrite) CGRect button1Bounds; @property (nonatomic, strong) UIDynamicAnimator *animator; @end !!@implementation APLCustomDynamicItemViewController !- (void)viewDidLoad { ! // Save the button's initial bounds. self.button1Bounds = self.button1.bounds; // Force the button image to scale with its bounds. self.button1.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; self.button1.contentVerticalAlignment = UIControlContentHorizontalAlignmentFill; } !// ... continue !@end

Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end

Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end

Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end

Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end

Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end

Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end

Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end

Example 2: remap center property

19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped

Example 2: remap center property

19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped

Example 2: remap center property

19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped

Example 2: remap center property

19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped

Example 2: remap center property

19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped

Example 2: remap center property

19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped

Example 2: remap center property

Dynamics & Collection View

Dynamics & UICollectionViews

• UICollectionViewLayoutAttributes conform to UIDynamicItem

Dynamics & UICollectionViews

• UICollectionViewLayoutAttributes conform to UIDynamicItem

•Can use UIKit Dynamics with collection view

Dynamics & UICollectionViews

• UICollectionViewLayoutAttributes conform to UIDynamicItem

•Can use UIKit Dynamics with collection view

• How

Dynamics & UICollectionViews

• UICollectionViewLayoutAttributes conform to UIDynamicItem

•Can use UIKit Dynamics with collection view

• How

•Use UIKit Dynamics for very specific animations

Dynamics & UICollectionViews

• UICollectionViewLayoutAttributes conform to UIDynamicItem

•Can use UIKit Dynamics with collection view

• How

•Use UIKit Dynamics for very specific animations

• create UIDynamicAnimator as needed and discard later

Dynamics & UICollectionViews

• UICollectionViewLayoutAttributes conform to UIDynamicItem

•Can use UIKit Dynamics with collection view

• How

•Use UIKit Dynamics for very specific animations

• create UIDynamicAnimator as needed and discard later

•Animate a subset of a layout

Dynamics & UICollectionViews

• UICollectionViewLayoutAttributes conform to UIDynamicItem

•Can use UIKit Dynamics with collection view

• How

•Use UIKit Dynamics for very specific animations

• create UIDynamicAnimator as needed and discard later

•Animate a subset of a layout

•Build an entire layout with UIKit Dynamics

Dynamics & UICollectionViews

• UICollectionViewLayoutAttributes conform to UIDynamicItem

•Can use UIKit Dynamics with collection view

• How

•Use UIKit Dynamics for very specific animations

• create UIDynamicAnimator as needed and discard later

•Animate a subset of a layout

•Build an entire layout with UIKit Dynamics

•performace: better for small data source

Basic steps

•Create the the UICollectionViewLayout instance

Basic steps

•Create the the UICollectionViewLayout instance

•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;

animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];

Basic steps

•Create the the UICollectionViewLayout instance

•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;

animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];

Basic steps

•Create the the UICollectionViewLayout instance

•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;

animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];

Basic steps

•Create the the UICollectionViewLayout instance

•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;

animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];

Basic steps

•Create the the UICollectionViewLayout instance

•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;

animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];

• Create behaviors and add UICollectionViewLayoutAttributes to these behaviors

Basic steps

•Create the the UICollectionViewLayout instance

•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;

animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];

• Create behaviors and add UICollectionViewLayoutAttributes to these behaviors UICollectionViewLayoutAttributes *attribute = ...;

UIAttachmentBehavior *spring;

spring = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:anchorPoint];

...

Basic steps

•Create the the UICollectionViewLayout instance

•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;

animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];

• Create behaviors and add UICollectionViewLayoutAttributes to these behaviors UICollectionViewLayoutAttributes *attribute = ...;

UIAttachmentBehavior *spring;

spring = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:anchorPoint];

...

Basic steps

•Create the the UICollectionViewLayout instance

•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;

animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];

• Create behaviors and add UICollectionViewLayoutAttributes to these behaviors UICollectionViewLayoutAttributes *attribute = ...;

UIAttachmentBehavior *spring;

spring = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:anchorPoint];

...

UIKit Dynamics Support for UICollectionViews

UIKit Dynamics Support for UICollectionViews

Dynamics has convenience support for UICollectionView

UIKit Dynamics Support for UICollectionViews

Dynamics has convenience support for UICollectionView

•Dynamics automatically invalidate layout as needed

UIKit Dynamics Support for UICollectionViews

Dynamics has convenience support for UICollectionView

•Dynamics automatically invalidate layout as needed

•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView

UIKit Dynamics Support for UICollectionViews

Dynamics has convenience support for UICollectionView

•Dynamics automatically invalidate layout as needed

•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView

• UIDynamicAnimator provide conveniece method to implemement custom layout

UIKit Dynamics Support for UICollectionViews

Dynamics has convenience support for UICollectionView

•Dynamics automatically invalidate layout as needed

•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView

• UIDynamicAnimator provide conveniece method to implemement custom layout- (UICollectionViewLayoutAttributes*)layoutAttributesForCellAtIndexPath:(NSIndexPath*)ip;

UIKit Dynamics Support for UICollectionViews

Dynamics has convenience support for UICollectionView

•Dynamics automatically invalidate layout as needed

•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView

• UIDynamicAnimator provide conveniece method to implemement custom layout- (UICollectionViewLayoutAttributes*)layoutAttributesForCellAtIndexPath:(NSIndexPath*)ip;

- (UICollectionViewLayoutAttributes*)layoutAttributesForSupplementaryViewOfKind:(NSString *)k atIndexPath:(NSIndexPath *)ip;

UIKit Dynamics Support for UICollectionViews

Dynamics has convenience support for UICollectionView

•Dynamics automatically invalidate layout as needed

•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView

• UIDynamicAnimator provide conveniece method to implemement custom layout- (UICollectionViewLayoutAttributes*)layoutAttributesForCellAtIndexPath:(NSIndexPath*)ip;

- (UICollectionViewLayoutAttributes*)layoutAttributesForSupplementaryViewOfKind:(NSString *)k atIndexPath:(NSIndexPath *)ip;

- (UICollectionViewLayoutAttributes*)layoutAttributesForDecorationViewOfKind:(NSString*)k atIndexPath:(NSIndexPath *)ip;

Collection View Layout Updates

Collection View Layout Updates

Use usual UICollectionViewLayout methods for layout update: 

Collection View Layout Updates

Use usual UICollectionViewLayout methods for layout update: • prepareLayout

Collection View Layout Updates

Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state 

Collection View Layout Updates

Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state 

•prepareForCollectionViewUpdates

Collection View Layout Updates

Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state 

•prepareForCollectionViewUpdates

•opportunity to add UICollectionViewLayoutAttributes to behaviors.

Collection View Layout Updates

Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state 

•prepareForCollectionViewUpdates

•opportunity to add UICollectionViewLayoutAttributes to behaviors.

• layoutAttributesForElementsInRect

Collection View Layout Updates

Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state 

•prepareForCollectionViewUpdates

•opportunity to add UICollectionViewLayoutAttributes to behaviors.

• layoutAttributesForElementsInRect • UIDynamicAnimator has itemsInRect

Example: collection view

Example: collection view

@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end

Example: collection view

@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end

Example: collection view

@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end

Example: collection view

@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end

Example: collection view

@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end

Example: collection view

@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end

Example: collection view

@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; ! NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end

Example: collection view

@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; ! NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end

Example: collection view

@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; ! NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end

Example: collection view

@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; ! NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end

Example: collection view

@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; ! NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end

Example: collection view

@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; ! NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end

Example: collection view

@import UIKit; !@interface DPDynamicCollectionViewViewController : UIViewController @end !!!!!const NSInteger kCellCount = 20; !@interface DPDynamicCollectionViewViewController() <UICollectionViewDataSource, UICollectionViewDelegate> ! @property (weak, nonatomic) IBOutlet UICollectionView *collectionView; ! @property (strong, nonatomic) UICollectionViewFlowLayout *flowLayout; ! @property (strong, nonatomic) NSMutableArray *colors; !@end !!

Example: collection view

@import UIKit; !@interface DPDynamicCollectionViewViewController : UIViewController @end !!!!!const NSInteger kCellCount = 20; !@interface DPDynamicCollectionViewViewController() <UICollectionViewDataSource, UICollectionViewDelegate> ! @property (weak, nonatomic) IBOutlet UICollectionView *collectionView; ! @property (strong, nonatomic) UICollectionViewFlowLayout *flowLayout; ! @property (strong, nonatomic) NSMutableArray *colors; !@end !!

Example: collection view

@import UIKit; !@interface DPDynamicCollectionViewViewController : UIViewController @end !!!!!const NSInteger kCellCount = 20; !@interface DPDynamicCollectionViewViewController() <UICollectionViewDataSource, UICollectionViewDelegate> ! @property (weak, nonatomic) IBOutlet UICollectionView *collectionView; ! @property (strong, nonatomic) UICollectionViewFlowLayout *flowLayout; ! @property (strong, nonatomic) NSMutableArray *colors; !@end !!

Example: collection view

@implementation DPDynamicCollectionViewViewController !... !- (void)viewDidLoad { [super viewDidLoad]; ! self.colors = [self cellColors]; ! [self.collectionView registerClass:[DPCollectionViewCell class] forCellWithReuseIdentifier:[DPCollectionViewCell cellIdentifier]]; self.flowLayout = [[DPProportionalSpringFlowLayout alloc] init]; [self.collectionView setCollectionViewLayout:[self flowLayout]]; !} !// ... continue !!!!@end

Example: collection view

@implementation DPDynamicCollectionViewViewController !... !- (void)viewDidLoad { [super viewDidLoad]; ! self.colors = [self cellColors]; ! [self.collectionView registerClass:[DPCollectionViewCell class] forCellWithReuseIdentifier:[DPCollectionViewCell cellIdentifier]]; self.flowLayout = [[DPProportionalSpringFlowLayout alloc] init]; [self.collectionView setCollectionViewLayout:[self flowLayout]]; !} !// ... continue !!!!@end

Example: collection view

@implementation DPDynamicCollectionViewViewController !... !- (void)viewDidLoad { [super viewDidLoad]; ! self.colors = [self cellColors]; ! [self.collectionView registerClass:[DPCollectionViewCell class] forCellWithReuseIdentifier:[DPCollectionViewCell cellIdentifier]]; self.flowLayout = [[DPProportionalSpringFlowLayout alloc] init]; [self.collectionView setCollectionViewLayout:[self flowLayout]]; !} !// ... continue !!!!@end

Example: collection view

@implementation DPDynamicCollectionViewViewController !// ... continue form previous slide !!- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return kCellCount; } !- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ! DPCollectionViewCell *cell; cell = (DPCollectionViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier: [DPCollectionViewCell cellIdentifier] forIndexPath:indexPath]; ! [self configureCell:cell forItemAtIndexPath:indexPath]; return cell; } !@end

Example: collection view

@implementation DPDynamicCollectionViewViewController !// ... continue form previous slide !!- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return kCellCount; } !- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ! DPCollectionViewCell *cell; cell = (DPCollectionViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier: [DPCollectionViewCell cellIdentifier] forIndexPath:indexPath]; ! [self configureCell:cell forItemAtIndexPath:indexPath]; return cell; } !@end

Example: collection view

@implementation DPDynamicCollectionViewViewController !// ... continue form previous slide !!- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return kCellCount; } !- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ! DPCollectionViewCell *cell; cell = (DPCollectionViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier: [DPCollectionViewCell cellIdentifier] forIndexPath:indexPath]; ! [self configureCell:cell forItemAtIndexPath:indexPath]; return cell; } !@end

Conclusion

Tips

•Build iteratively

Tips

•Build iteratively

•Check for setup which don’t have solutions

Tips

•Build iteratively

•Check for setup which don’t have solutions

Tips

•Build iteratively

•Check for setup which don’t have solutions

Tips

•Build iteratively

•Check for setup which don’t have solutions

•Collision only for rectangle objects

Tips

•Build iteratively

•Check for setup which don’t have solutions

•Collision only for rectangle objects

Tips

•Build iteratively

•Check for setup which don’t have solutions

•Collision only for rectangle objects

•Not an physics-accurate simulation tool

Tips

•Build iteratively

•Check for setup which don’t have solutions

•Collision only for rectangle objects

•Not an physics-accurate simulation tool

•Not for games

Tips

•Build iteratively

•Check for setup which don’t have solutions

•Collision only for rectangle objects

•Not an physics-accurate simulation tool

•Not for games

• use Sprite Kit

Tips

•Build iteratively

•Check for setup which don’t have solutions

•Collision only for rectangle objects

•Not an physics-accurate simulation tool

•Not for games

• use Sprite Kit

•Focus on the user experience

Animations and Interactions

•Can combine all previous techniques

Animations and Interactions

•Can combine all previous techniques

•Core Animation

Animations and Interactions

•Can combine all previous techniques

•Core Animation

•UIView animations+(void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;

Animations and Interactions

•Can combine all previous techniques

•Core Animation

•UIView animations+(void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;

•Motion effects

Animations and Interactions

•Can combine all previous techniques

•Core Animation

•UIView animations+(void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;

•Motion effects

•Gestures

Endings

"With great power comes great responsibility."

Francois-Marie Arouet a.k.a. Voltaire

References

•Apple documentation

•WWDC 2013 sessions206 Getting Started with UIKit Dynamics221 Advanced Techniques with UIKit Dynamics217 Exploring Scroll Views in iOS 7218 Custom Transitions Using View Controllers226 Implementing Engaging UI on iOS

References

• 3rd party docsiOS 7 by tutorials Chap. 2 (by raywenderlich.com)Objc.io issue #5

•Example codeDynamicPlaygroundUIKit Dynamics Catalog (iOS Dev Library Sample Code)

Q & A

… and one more thing

It’s beer O’Clock

THANKS