Your SlideShare is downloading. ×
0
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
#pragma conf 2013  - UIKit dynamics
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

#pragma conf 2013 - UIKit dynamics

398

Published on

Published in: Technology, Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
398
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
21
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. UIKit Dynamics Renzo G. Pretto iOS Developer
  • 2. Who’s talking
  • 3. Who’s talking
  • 4. About me Renzo iOS Developer H-art ! #pragma mark founder renzo.pretto@pragmamark.org ! @rgpretto
  • 5. Conference Hashtag #pragmaconf
  • 6. Today Agenda • Introduction and core concepts
  • 7. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors
  • 8. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors
  • 9. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts
  • 10. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem
  • 11. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem • Collection View
  • 12. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem • Collection View • Conclusion
  • 13. UIKit Dynamics
  • 14. UIKit Dynamics
  • 15. UIKit Dynamics
  • 16. Architecture UIDynamicAnimator
  • 17. Architecture UIDynamicAnimator UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior
  • 18. Architecture UIDynamicAnimator UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior
  • 19. Architecture UIDynamicAnimator UIDynamicBehavior View UIDynamicBehavior UIDynamicBehavior
  • 20. Architecture UIDynamicAnimator UIDynamicBehavior UIDynamicBehavior View View UIDynamicBehavior
  • 21. Architecture UIDynamicAnimator UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior View View View
  • 22. Architecture UIDynamicAnimator Reference view UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior View View View
  • 23. Architecture UIDynamicAnimator Reference view UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior View View View
  • 24. UIDynamicAnimator UIDynamicAnimator Reference view
  • 25. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator Reference view
  • 26. UIDynamicAnimator • Define the coordinate system • Wraps underline engine UIDynamicAnimator Reference view
  • 27. UIDynamicAnimator • Define the coordinate system • Wraps underline engine • Keeps track of all the associated behaviors UIDynamicAnimator Reference view
  • 28. UIDynamicAnimator • Define the coordinate system • Wraps underline engine • Keeps track of all the associated behaviors • Run and optimize the animation UIDynamicAnimator Reference view
  • 29. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • Run and optimize the animation • Each dynamic animator is independent from other dynamic animators
  • 30. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • 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]; ...
  • 31. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • 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]; ...
  • 32. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • 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]; ...
  • 33. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator • Wraps underline engine • Keeps track of all the associated behaviors Reference view • 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]; ...
  • 34. UIDynamicAnimatorDelegate @protocol UIDynamicAnimatorDelegate <NSObject> ! @optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; ! @end
  • 35. UIDynamicAnimatorDelegate @protocol UIDynamicAnimatorDelegate <NSObject> ! @optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; ! @end • Notify pausing and resuming of UIKit Dynamic animator
  • 36. UIDynamicBehaviour UIDynamicBehavior
  • 37. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior • Associated to UIDynamicAnimator
  • 38. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior • Associated to UIDynamicAnimator • Add and remove behaviours to an animator at any times
  • 39. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior View View • Associated to UIDynamicAnimator • Add and remove behaviours to an animator at any times • Usually associated to a view or a set of view
  • 40. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior View View UIDynamicBehavior View • Associated to UIDynamicAnimator • Add and remove behaviours to an animator at any times • Usually associated to a view or a set of view • Composed
  • 41. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior View View UIDynamicBehavior View • 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
  • 42. Behaviors Common characteristics • Initialized with items to animate
  • 43. Behaviors Common characteristics • Initialized with items to animate • Items can be added to behavior at any times
  • 44. Behaviors Common characteristics • Initialized with items to animate • Items can be added to behavior at any times • Behaviour can be configured before or after add to an animator
  • 45. Behaviors Common characteristics • Initialized 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
  • 46. Primitive behaviors
  • 47. Default Behaviors UIDynamicBehavior
  • 48. Default Behaviors UIDynamicBehavior • Gravity UIGravityBehavior
  • 49. Default Behaviors UIDynamicBehavior • Gravity • Collisions UIGravityBehavior UICollisionBehavior
  • 50. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior
  • 51. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments • Snap UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior
  • 52. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior • Snap UISnapBehavior • Forces UIPushBehavior
  • 53. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior • Snap UISnapBehavior • Forces UIPushBehavior • Item properties UIDynamicItemBehavior
  • 54. UIGravityBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 55. UIGravityBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 56. UIGravityBehavior
  • 57. 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
  • 58. 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
  • 59. 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
  • 60. 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
  • 61. 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
  • 62. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection;
  • 63. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection; or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
  • 64. 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)
  • 65. 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)
  • 66. 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 - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item; (0.0, 1.0)
  • 67. UICollisionBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 68. UICollisionBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 69. UICollisionBehavior
  • 70. UICollisionBehavior @interface DPGravityCollisionViewController : 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
  • 71. UICollisionBehavior @interface DPGravityCollisionViewController : 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
  • 72. UICollisionBehavior @interface DPGravityCollisionViewController : 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
  • 73. UICollisionBehavior @interface DPGravityCollisionViewController : 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
  • 74. UICollisionBehavior @interface DPGravityCollisionViewController : 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
  • 75. UICollisionBehavior @interface DPGravityCollisionViewController : 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
  • 76. UICollisionBehavior @interface DPGravityCollisionViewController : 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
  • 77. Collision Boundaries • Can specify different boundaries
  • 78. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
  • 79. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary; • Insets to reference view - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
  • 80. 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;
  • 81. 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;
  • 82. 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;
  • 83. 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
  • 84. Collision Mode • Property collisionmode
  • 85. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
  • 86. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries
  • 87. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries • UICollisionBehaviorModeItems
  • 88. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries • UICollisionBehaviorModeItems • UICollisionBehaviorModeEverything (default)
  • 89. Tips
  • 90. Tips • Can use multiple collision behaviors
  • 91. Tips • Can use multiple collision behaviors • Add and remove items to this behaviour anytime - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;
  • 92. Tips • Can use multiple collision behaviors • Add and remove items to this behaviour anytime - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item; • Collision detection have CPU cost
  • 93. UICollisionBehaviorDelegate • Methods that inform collision start / end between view
  • 94. 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;
  • 95. 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
  • 96. 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;
  • 97. 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;
  • 98. 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
  • 99. UIAttachmentBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 100. UIAttachmentBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 101. UIAttachmentBehavior
  • 102. 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
  • 103. 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
  • 104. 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
  • 105. 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
  • 106. 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
  • 107. 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
  • 108. UIAttachmentBehavior
  • 109. UIAttachmentBehavior
  • 110. UIAttachmentBehavior • View connected to an attachment point
  • 111. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
  • 112. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point; • Two views connected together
  • 113. 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;
  • 114. 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
  • 115. 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;
  • 116. 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;
  • 117. Springs • Springs
  • 118. Springs • Springs @property (readwrite, nonatomic) CGFloat damping;
  • 119. Springs • Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
  • 120. Springs • Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
  • 121. UISnapBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 122. UISnapBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 123. UISnapBehavior
  • 124. UISnapBehavior
  • 125. UISnapBehavior interface 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
  • 126. UISnapBehavior interface 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
  • 127. UISnapBehavior interface 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
  • 128. UISnapBehavior interface 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
  • 129. UISnapBehavior interface 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
  • 130. UISnapBehavior interface 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
  • 131. UISnapBehavior • Snap view in place in non rotated state
  • 132. UISnapBehavior • Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;
  • 133. UISnapBehavior • Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point; • Customize the dumping effects
  • 134. 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;
  • 135. UIPushBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 136. UIPushBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 137. UIPushBehavior ~ =m~ F a
  • 138. UIPushBehavior ~ F =m~ a
  • 139. UIPushBehavior ~ F = m ~ , apply force to views: a •
  • 140. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
  • 141. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • Force vector expressed in two way:
  • 142. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • Force vector expressed in two way: @property (readwrite, nonatomic) CGVector pushDirection;
  • 143. UIPushBehavior ~ F = m ~ , apply force to views: a • - (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;
  • 144. UIPushBehavior • Customize where apply this force in the view
  • 145. UIPushBehavior • Customize where apply this force in the view
  • 146. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  • 147. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  • 148. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  • 149. 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
  • 150. 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;
  • 151. UIPushBehavior Mode
  • 152. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
  • 153. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous
  • 154. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous • force still be applied while behaviour is active
  • 155. 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
  • 156. 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
  • 157. 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
  • 158. 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)
  • 159. 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
  • 160. 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;
  • 161. Example: force comparison ~ F =m~ a ~ F ~= a m
  • 162. Example: gravity comparison
  • 163. Feel The Force!
  • 164. Feel The Force! • Gravity
  • 165. Feel The Force! • Gravity • views accelerate with the same rate
  • 166. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode
  • 167. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode • the smaller views accelerate more
  • 168. 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
  • 169. 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
  • 170. 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
  • 171. Unit of Measure • Real world: Newton
  • 172. Unit of Measure • Real world: Newton 1 Newton accelerate 1Kg at a rate of 1 m/s2 •
  • 173. 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
  • 174. 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”
  • 175. UIDynamicItemBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 176. UIDynamicItemBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  • 177. UIDynamicItemBehavior • Customize dynamics properties for items
  • 178. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity;
  • 179. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction;
  • 180. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density;
  • 181. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) CGFloat CGFloat CGFloat CGFloat elasticity; friction; density; resistance;
  • 182. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat CGFloat CGFloat CGFloat CGFloat elasticity; friction; density; resistance; angularResistance;
  • 183. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; BOOL allowsRotation;
  • 184. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; BOOL allowsRotation; • Add linear velocity (points per second) - (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item; - (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;
  • 185. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; 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;
  • 186. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; 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
  • 187. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; 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
  • 188. UIDynamicItemBehavior • Customize dynamics properties for items @property @property @property @property @property @property (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, (readwrite, nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) nonatomic) CGFloat elasticity; CGFloat friction; CGFloat density; CGFloat resistance; CGFloat angularResistance; 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
  • 189. Custom behaviors
  • 190. Custom Behavior • Can subclass UIDynamicBehavior
  • 191. Custom Behavior • Can subclass UIDynamicBehavior • add child behavior - (void)addChildBehavior:(UIDynamicBehavior *)behavior; - (void)removeChildBehavior:(UIDynamicBehavior *)behavior; @property (nonatomic, readonly, copy) NSArray* childBehaviors;
  • 192. 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
  • 193. Example: gravity & collision
  • 194. 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
  • 195. 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
  • 196. 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
  • 197. 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
  • 198. 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
  • 199. 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
  • 200. 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
  • 201. 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
  • 202. 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
  • 203. 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
  • 204. 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
  • 205. 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
  • 206. 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
  • 207. 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
  • 208. 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
  • 209. 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 = @[...]; DPGravityCollisionBehavior *gravityAndCollision; gravityAndCollision= [[DPGravityCollisionBehavior alloc] initWithItems:items]; [self.animator addBehavior:gravityAndCollision]; } ! @end
  • 210. Action Block • Can define per-step actions
  • 211. Action Block • Can define per-step actions @property (nonatomic, copy) void (^action)(void);
  • 212. Action Block • Can define per-step actions @property (nonatomic, copy) void (^action)(void); • UIDynamicAnimator invoke this block in each simulation step
  • 213. 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
  • 214. UIDynamicItem protocol
  • 215. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end
  • 216. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • All items animated by UIKit Dynamics must implement this protocol
  • 217. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • All items animated by UIKit Dynamics must implement this protocol • Describe what UIKit Dynamics needs to animate an item
  • 218. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • All items animated by UIKit Dynamics must implement this protocol • Describe what UIKit Dynamics needs to animate an item • position: center
  • 219. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • All items animated by UIKit Dynamics must implement this protocol • Describe what UIKit Dynamics needs to animate an item • position: center • size: bounds
  • 220. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end • 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)
  • 221. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit
  • 222. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
  • 223. 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
  • 224. 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
  • 225. 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
  • 226. 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
  • 227. 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
  • 228. 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
  • 229. 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
  • 230. UIDynamicItem Protocol • All items animated by UIKit Dynamics must implement this protocol
  • 231. UIDynamicItem Protocol • All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol @interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... }
  • 232. 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 > { ... }
  • 233. 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 > { ... }
  • 234. Architecture UIDynamicAnimator Reference view UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior View View View
  • 235. Architecture UIDynamicAnimator Reference view UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior NSObject! <UIDynamicItem> NSObject! <UIDynamicItem> NSObject! <UIDynamicItem>
  • 236. 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
  • 237. 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
  • 238. 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
  • 239. 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
  • 240. 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
  • 241. 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
  • 242. 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
  • 243. 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
  • 244. 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
  • 245. 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
  • 246. 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
  • 247. 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
  • 248. Example 1: conform to UIDynamicItem
  • 249. Example 1: conform to UIDynamicItem 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 ! 18:58:05.598 18:58:05.609 18:58:05.611 18:58:05.626 18:58:05.629 18:58:05.642 18:58:05.645 18:58:05.659 18:58:05.661 18:58:05.675 18:58:05.677 DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] Animator is running Center = {50, 50.04797} Transform = [1, 0, -0, 1, Center = {50, 50.447464} Transform = [1, 0, -0, 1, Center = {50, 51.054173} Transform = [1, 0, -0, 1, Center = {50, 51.915657} Transform = [1, 0, -0, 1, Center = {50, 53.031506} Transform = [1, 0, -0, 1, 18:58:08.742 18:58:08.744 18:58:08.759 18:58:08.761 18:58:08.775 18:58:08.777 18:58:08.792 18:58:08.794 18:58:08.809 18:58:08.810 18:58:08.812 DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Animator is stopped 0, 0] 0, 0] 0, 0] 0, 0] 0, 0] ... ! 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 0, 0] 0, 0] 0, 0] 0, 0] 0, 0]
  • 250. Example 1: conform to UIDynamicItem 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 ! 18:58:05.598 18:58:05.609 18:58:05.611 18:58:05.626 18:58:05.629 18:58:05.642 18:58:05.645 18:58:05.659 18:58:05.661 18:58:05.675 18:58:05.677 DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] Animator is running Center = {50, 50.04797} Transform = [1, 0, -0, 1, Center = {50, 50.447464} Transform = [1, 0, -0, 1, Center = {50, 51.054173} Transform = [1, 0, -0, 1, Center = {50, 51.915657} Transform = [1, 0, -0, 1, Center = {50, 53.031506} Transform = [1, 0, -0, 1, 18:58:08.742 18:58:08.744 18:58:08.759 18:58:08.761 18:58:08.775 18:58:08.777 18:58:08.792 18:58:08.794 18:58:08.809 18:58:08.810 18:58:08.812 DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] DynamicsPlayground[771:60b] Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Center = {50, 518.13135} Transform = [1, 0, -0, 1, Animator is stopped 0, 0] 0, 0] 0, 0] 0, 0] 0, 0] ... ! 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 2013-10-17 0, 0] 0, 0] 0, 0] 0, 0] 0, 0]
  • 251. UIDynamicItem Use Case • Can use a single dynamic item to animate different views
  • 252. UIDynamicItem Use Case • Can use a single dynamic item to animate different views • Can map center or transform to something else
  • 253. 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 isn’t a view or a collection view use a UIDynamicItem
  • 254. 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 isn’t a view or a collection view use a UIDynamicItem
  • 255. Example 2: remap center property
  • 256. 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
  • 257. 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
  • 258. 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
  • 259. 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
  • 260. 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
  • 261. 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
  • 262. 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
  • 263. 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
  • 264. 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
  • 265. 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
  • 266. 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
  • 267. 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
  • 268. 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
  • 269. 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
  • 270. 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
  • 271. 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
  • 272. Example 2: remap center property
  • 273. Example 2: remap center property 19:18:56.545 19:18:56.547 19:18:56.549 19:18:56.550 19:18:56.551 19:18:56.552 19:18:56.553 19:18:56.556 19:18:56.561 19:18:56.563 19:18:56.575 19:18:56.578 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator is running -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping center]:68 {150, 46} center]:68 {150, 46} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:19:02.527 19:19:02.529 19:19:02.542 19:19:02.545 19:19:02.547 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator stopped setCenter:]:81 {150.07957, 46.079357} setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] setCenter:]:81 {150.07266, 46.072491} setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] ! ... ! setCenter:]:81 {150, 45.999996} setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] setCenter:]:81 {153.80513, 49.805138} setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0]
  • 274. Example 2: remap center property 19:18:56.545 19:18:56.547 19:18:56.549 19:18:56.550 19:18:56.551 19:18:56.552 19:18:56.553 19:18:56.556 19:18:56.561 19:18:56.563 19:18:56.575 19:18:56.578 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator is running -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping center]:68 {150, 46} center]:68 {150, 46} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:19:02.527 19:19:02.529 19:19:02.542 19:19:02.545 19:19:02.547 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator stopped setCenter:]:81 {150.07957, 46.079357} setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] setCenter:]:81 {150.07266, 46.072491} setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] ! ... ! setCenter:]:81 {150, 45.999996} setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] setCenter:]:81 {153.80513, 49.805138} setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0]
  • 275. Example 2: remap center property 19:18:56.545 19:18:56.547 19:18:56.549 19:18:56.550 19:18:56.551 19:18:56.552 19:18:56.553 19:18:56.556 19:18:56.561 19:18:56.563 19:18:56.575 19:18:56.578 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator is running -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping center]:68 {150, 46} center]:68 {150, 46} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:19:02.527 19:19:02.529 19:19:02.542 19:19:02.545 19:19:02.547 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator stopped setCenter:]:81 {150.07957, 46.079357} setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] setCenter:]:81 {150.07266, 46.072491} setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] ! ... ! setCenter:]:81 {150, 45.999996} setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] setCenter:]:81 {153.80513, 49.805138} setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0]
  • 276. Example 2: remap center property 19:18:56.545 19:18:56.547 19:18:56.549 19:18:56.550 19:18:56.551 19:18:56.552 19:18:56.553 19:18:56.556 19:18:56.561 19:18:56.563 19:18:56.575 19:18:56.578 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator is running -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping center]:68 {150, 46} center]:68 {150, 46} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:19:02.527 19:19:02.529 19:19:02.542 19:19:02.545 19:19:02.547 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator stopped setCenter:]:81 {150.07957, 46.079357} setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] setCenter:]:81 {150.07266, 46.072491} setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] ! ... ! setCenter:]:81 {150, 45.999996} setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] setCenter:]:81 {153.80513, 49.805138} setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0]
  • 277. Example 2: remap center property 19:18:56.545 19:18:56.547 19:18:56.549 19:18:56.550 19:18:56.551 19:18:56.552 19:18:56.553 19:18:56.556 19:18:56.561 19:18:56.563 19:18:56.575 19:18:56.578 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator is running -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping center]:68 {150, 46} center]:68 {150, 46} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:19:02.527 19:19:02.529 19:19:02.542 19:19:02.545 19:19:02.547 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator stopped setCenter:]:81 {150.07957, 46.079357} setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] setCenter:]:81 {150.07266, 46.072491} setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] ! ... ! setCenter:]:81 {150, 45.999996} setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] setCenter:]:81 {153.80513, 49.805138} setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0]
  • 278. Example 2: remap center property 19:18:56.545 19:18:56.547 19:18:56.549 19:18:56.550 19:18:56.551 19:18:56.552 19:18:56.553 19:18:56.556 19:18:56.561 19:18:56.563 19:18:56.575 19:18:56.578 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator is running -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping center]:68 {150, 46} center]:68 {150, 46} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} bounds]:55 {{0, 0}, {150, 46}} transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:19:02.527 19:19:02.529 19:19:02.542 19:19:02.545 19:19:02.547 -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping -[APLPositionToBoundsMapping Animator stopped setCenter:]:81 {150.07957, 46.079357} setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] setCenter:]:81 {150.07266, 46.072491} setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] ! ... ! setCenter:]:81 {150, 45.999996} setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] setCenter:]:81 {153.80513, 49.805138} setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0]
  • 279. Dynamics & Collection View
  • 280. Dynamics & UICollectionViews • UICollectionViewLayoutAttributes conform to UIDynamicItem
  • 281. Dynamics & UICollectionViews • UICollectionViewLayoutAttributes conform to UIDynamicItem • Can use UIKit Dynamics with collection view
  • 282. Dynamics & UICollectionViews • UICollectionViewLayoutAttributes conform to UIDynamicItem • Can use UIKit Dynamics with collection view • How
  • 283. Dynamics & UICollectionViews • UICollectionViewLayoutAttributes conform to UIDynamicItem • Can use UIKit Dynamics with collection view • How • Use UIKit Dynamics for very specific animations
  • 284. 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
  • 285. 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
  • 286. 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
  • 287. 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
  • 288. Basic steps • Create the the UICollectionViewLayout instance
  • 289. Basic steps • Create the the UICollectionViewLayout instance • Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...; animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
  • 290. Basic steps • Create the the UICollectionViewLayout instance • Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...; animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
  • 291. Basic steps • Create the the UICollectionViewLayout instance • Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...; animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
  • 292. Basic steps • Create the the UICollectionViewLayout instance • Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...; animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
  • 293. 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
  • 294. 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]; ...
  • 295. 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]; ...
  • 296. 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]; ...
  • 297. UIKit Dynamics Support for UICollectionViews Dynamics has convenience support for UICollectionView
  • 298. UIKit Dynamics Support for UICollectionViews Dynamics has convenience support for UICollectionView • Dynamics automatically invalidate layout as needed
  • 299. 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
  • 300. 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 • provide convenience method to implement custom layout UIDynamicAnimator
  • 301. 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 • provide convenience method to implement custom layout UIDynamicAnimator - (UICollectionViewLayoutAttributes*)layoutAttributesForCellAtIndexPath: (NSIndexPath*)ip;
  • 302. 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 • provide convenience method to implement custom layout UIDynamicAnimator - (UICollectionViewLayoutAttributes*)layoutAttributesForCellAtIndexPath: (NSIndexPath*)ip; (UICollectionViewLayoutAttributes*)layoutAttributesForSupplementaryViewOfKind: (NSString *)k atIndexPath:(NSIndexPath *)ip;
  • 303. 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 • provide convenience method to implement custom layout UIDynamicAnimator - (UICollectionViewLayoutAttributes*)layoutAttributesForCellAtIndexPath: (NSIndexPath*)ip; (UICollectionViewLayoutAttributes*)layoutAttributesForSupplementaryViewOfKind: (NSString *)k atIndexPath:(NSIndexPath *)ip; - (UICollectionViewLayoutAttributes*)layoutAttributesForDecorationViewOfKind: (NSString*)k atIndexPath:(NSIndexPath *)ip;
  • 304. Collection View Layout Updates Use usual UICollectionViewLayout methods for layout update: 
  • 305. Collection View Layout Updates Use usual UICollectionViewLayout methods for layout update:  • prepareLayout
  • 306. Collection View Layout Updates Use usual UICollectionViewLayout methods for layout update:  • prepareLayout •used when instantiate an animator or create initial state 
  • 307. Collection View Layout Updates Use usual UICollectionViewLayout methods for layout update:  • prepareLayout •used when instantiate an animator or create initial state  •prepareForCollectionViewUpdates
  • 308. 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 behaviors. UICollectionViewLayoutAttributes to
  • 309. 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 behaviors. • layoutAttributesForElementsInRect to
  • 310. 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 behaviors. • layoutAttributesForElementsInRect • UIDynamicAnimator has itemsInRect to
  • 311. Example: collection view
  • 312. Example: collection view @interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end ! ! ! @interface DPProportionalSpringFlowLayout () ! @property (strong, readwrite, nonatomic) UIDynamicAnimator ! @end ! @implementation DPProportionalSpringFlowLayout ! *dynamicAnimator; - (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]; } ! ... ! @end // continue
  • 313. Example: collection view @interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end ! ! ! @interface DPProportionalSpringFlowLayout () ! @property (strong, readwrite, nonatomic) UIDynamicAnimator ! @end ! @implementation DPProportionalSpringFlowLayout ! *dynamicAnimator; - (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]; } ! ... ! @end // continue
  • 314. Example: collection view @interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end ! ! ! @interface DPProportionalSpringFlowLayout () ! @property (strong, readwrite, nonatomic) UIDynamicAnimator ! @end ! @implementation DPProportionalSpringFlowLayout ! *dynamicAnimator; - (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]; } ! ... ! @end // continue
  • 315. Example: collection view @interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end ! ! ! @interface DPProportionalSpringFlowLayout () ! @property (strong, readwrite, nonatomic) UIDynamicAnimator ! @end ! @implementation DPProportionalSpringFlowLayout ! *dynamicAnimator; - (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]; } ! ... ! @end // continue
  • 316. Example: collection view @interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end ! ! ! @interface DPProportionalSpringFlowLayout () ! @property (strong, readwrite, nonatomic) UIDynamicAnimator ! @end ! @implementation DPProportionalSpringFlowLayout ! *dynamicAnimator; - (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]; } ! ... ! @end // continue
  • 317. Example: collection view @interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end ! ! ! @interface DPProportionalSpringFlowLayout () ! @property (strong, readwrite, nonatomic) UIDynamicAnimator ! @end ! @implementation DPProportionalSpringFlowLayout ! *dynamicAnimator; - (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]; } ! ... ! @end // continue
  • 318. 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
  • 319. 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
  • 320. 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
  • 321. 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
  • 322. 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
  • 323. 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
  • 324. 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
  • 325. 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
  • 326. 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
  • 327. 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
  • 328. 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
  • 329. 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
  • 330. 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
  • 331. 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
  • 332. 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
  • 333. 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
  • 334. 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 ! !
  • 335. 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 ! !
  • 336. 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 ! !
  • 337. 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
  • 338. 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
  • 339. 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
  • 340. 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
  • 341. 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
  • 342. 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
  • 343. Conclusion
  • 344. Long Story Short • Identify the type of dynamic items you want to animate
  • 345. Long Story Short • Identify the type of dynamic items you want to animate • Define container or reference view
  • 346. Long Story Short • Identify the type of dynamic items you want to animate • Define container or reference view • Create the behaviours
  • 347. 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
  • 348. 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
  • 349. Tips • Build iteratively
  • 350. Tips • Build iteratively • Check for setup which don’t have solutions
  • 351. Tips • Build iteratively • Check for setup which don’t have solutions
  • 352. Tips • Build iteratively • Check for setup which don’t have solutions
  • 353. Tips • Build iteratively • Check for setup which don’t have solutions • Collision only for rectangle objects
  • 354. Tips • Build iteratively • Check for setup which don’t have solutions • Collision only for rectangle objects
  • 355. Tips • Build iteratively • Check for setup which don’t have solutions • Collision only for rectangle objects • Not an physics-accurate simulation tool
  • 356. 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
  • 357. 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
  • 358. 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
  • 359. Animations and Interactions • Can combine all previous techniques
  • 360. Animations and Interactions • Can combine all previous techniques • Core Animation
  • 361. 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;
  • 362. 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
  • 363. 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
  • 364. Endings "With great power comes great responsibility." Francois-Marie Arouet aka Voltaire
  • 365. References • Apple documentation • WWDC 2013 sessions 206 Getting Started with UIKit Dynamics 221 Advanced Techniques with UIKit Dynamics 217 Exploring Scroll Views in iOS 7 218 Custom Transitions Using View Controllers 226 Implementing Engaging UI on iOS
  • 366. References • 3rd party docs iOS 7 by tutorials Chap. 2 (by raywenderlich.com) Objc.io issue #5 • Example code DynamicPlayground UIKit Dynamics Catalog (iOS Dev Library Sample Code)
  • 367. Q&A
  • 368. THANKS

×