#pragma conf 2013 - UIKit dynamics

765 views

Published on

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

No Downloads
Views
Total views
765
On SlideShare
0
From Embeds
0
Number of Embeds
91
Actions
Shares
0
Downloads
28
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

#pragma conf 2013 - UIKit dynamics

  1. 1. UIKit Dynamics Renzo G. Pretto iOS Developer
  2. 2. Who’s talking
  3. 3. Who’s talking
  4. 4. About me Renzo iOS Developer H-art ! #pragma mark founder renzo.pretto@pragmamark.org ! @rgpretto
  5. 5. Conference Hashtag #pragmaconf
  6. 6. Today Agenda • Introduction and core concepts
  7. 7. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors
  8. 8. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors
  9. 9. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts
  10. 10. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem
  11. 11. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem • Collection View
  12. 12. Today Agenda • Introduction and core concepts • Standard effects: dynamic behaviors • Custom effects: custom behaviors • Advanced concepts • UIDynamicItem • Collection View • Conclusion
  13. 13. UIKit Dynamics
  14. 14. UIKit Dynamics
  15. 15. UIKit Dynamics
  16. 16. Architecture UIDynamicAnimator
  17. 17. Architecture UIDynamicAnimator UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior
  18. 18. Architecture UIDynamicAnimator UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior
  19. 19. Architecture UIDynamicAnimator UIDynamicBehavior View UIDynamicBehavior UIDynamicBehavior
  20. 20. Architecture UIDynamicAnimator UIDynamicBehavior UIDynamicBehavior View View UIDynamicBehavior
  21. 21. Architecture UIDynamicAnimator UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior View View View
  22. 22. Architecture UIDynamicAnimator Reference view UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior View View View
  23. 23. Architecture UIDynamicAnimator Reference view UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior View View View
  24. 24. UIDynamicAnimator UIDynamicAnimator Reference view
  25. 25. UIDynamicAnimator • Define the coordinate system UIDynamicAnimator Reference view
  26. 26. UIDynamicAnimator • Define the coordinate system • Wraps underline engine UIDynamicAnimator Reference view
  27. 27. UIDynamicAnimator • Define the coordinate system • Wraps underline engine • Keeps track of all the associated behaviors UIDynamicAnimator Reference view
  28. 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. 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. 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. 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. 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. 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. 34. UIDynamicAnimatorDelegate @protocol UIDynamicAnimatorDelegate <NSObject> ! @optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; ! @end
  35. 35. UIDynamicAnimatorDelegate @protocol UIDynamicAnimatorDelegate <NSObject> ! @optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; ! @end • Notify pausing and resuming of UIKit Dynamic animator
  36. 36. UIDynamicBehaviour UIDynamicBehavior
  37. 37. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior • Associated to UIDynamicAnimator
  38. 38. UIDynamicBehaviour UIDynamicAnimator UIDynamicBehavior • Associated to UIDynamicAnimator • Add and remove behaviours to an animator at any times
  39. 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. 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. 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. 42. Behaviors Common characteristics • Initialized with items to animate
  43. 43. Behaviors Common characteristics • Initialized with items to animate • Items can be added to behavior at any times
  44. 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. 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. 46. Primitive behaviors
  47. 47. Default Behaviors UIDynamicBehavior
  48. 48. Default Behaviors UIDynamicBehavior • Gravity UIGravityBehavior
  49. 49. Default Behaviors UIDynamicBehavior • Gravity • Collisions UIGravityBehavior UICollisionBehavior
  50. 50. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior
  51. 51. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments • Snap UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior
  52. 52. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior • Snap UISnapBehavior • Forces UIPushBehavior
  53. 53. Default Behaviors UIDynamicBehavior • Gravity • Collisions • Attachments UIGravityBehavior UICollisionBehavior UIAttachmentBehavior • Snap UISnapBehavior • Forces UIPushBehavior • Item properties UIDynamicItemBehavior
  54. 54. UIGravityBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  55. 55. UIGravityBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  56. 56. UIGravityBehavior
  57. 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. 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. 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. 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. 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. 62. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection;
  63. 63. UIGravityBehavior • Defined by a gravity vector @property (readwrite, nonatomic) CGVector gravityDirection; or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
  64. 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. 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. 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. 67. UICollisionBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  68. 68. UICollisionBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  69. 69. UICollisionBehavior
  70. 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. 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. 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. 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. 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. 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. 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. 77. Collision Boundaries • Can specify different boundaries
  78. 78. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
  79. 79. Collision Boundaries • Can specify different boundaries • Reference view @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary; • Insets to reference view - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
  80. 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. 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. 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. 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. 84. Collision Mode • Property collisionmode
  85. 85. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
  86. 86. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries
  87. 87. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries • UICollisionBehaviorModeItems
  88. 88. Collision Mode • Property collisionmode @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode; • UICollisionBehaviorModeBoundaries • UICollisionBehaviorModeItems • UICollisionBehaviorModeEverything (default)
  89. 89. Tips
  90. 90. Tips • Can use multiple collision behaviors
  91. 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. 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. 93. UICollisionBehaviorDelegate • Methods that inform collision start / end between view
  94. 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. 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. 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. 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. 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. 99. UIAttachmentBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  100. 100. UIAttachmentBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  101. 101. UIAttachmentBehavior
  102. 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. 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. 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. 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. 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. 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. 108. UIAttachmentBehavior
  109. 109. UIAttachmentBehavior
  110. 110. UIAttachmentBehavior • View connected to an attachment point
  111. 111. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
  112. 112. UIAttachmentBehavior • View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point; • Two views connected together
  113. 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. 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. 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. 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. 117. Springs • Springs
  118. 118. Springs • Springs @property (readwrite, nonatomic) CGFloat damping;
  119. 119. Springs • Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
  120. 120. Springs • Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
  121. 121. UISnapBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  122. 122. UISnapBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  123. 123. UISnapBehavior
  124. 124. UISnapBehavior
  125. 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. 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. 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. 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. 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. 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. 131. UISnapBehavior • Snap view in place in non rotated state
  132. 132. UISnapBehavior • Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;
  133. 133. UISnapBehavior • Snap view in place in non rotated state - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point; • Customize the dumping effects
  134. 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. 135. UIPushBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  136. 136. UIPushBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  137. 137. UIPushBehavior ~ =m~ F a
  138. 138. UIPushBehavior ~ F =m~ a
  139. 139. UIPushBehavior ~ F = m ~ , apply force to views: a •
  140. 140. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
  141. 141. UIPushBehavior ~ F = m ~ , apply force to views: a • - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • Force vector expressed in two way:
  142. 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. 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. 144. UIPushBehavior • Customize where apply this force in the view
  145. 145. UIPushBehavior • Customize where apply this force in the view
  146. 146. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  147. 147. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  148. 148. UIPushBehavior • Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
  149. 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. 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. 151. UIPushBehavior Mode
  152. 152. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
  153. 153. UIPushBehavior Mode • Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode; • UIPushBehaviorModeContinuous
  154. 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. 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. 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. 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. 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. 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. 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. 161. Example: force comparison ~ F =m~ a ~ F ~= a m
  162. 162. Example: gravity comparison
  163. 163. Feel The Force!
  164. 164. Feel The Force! • Gravity
  165. 165. Feel The Force! • Gravity • views accelerate with the same rate
  166. 166. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode
  167. 167. Feel The Force! • Gravity • views accelerate with the same rate • Push behavior in continuos mode • the smaller views accelerate more
  168. 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. 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. 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. 171. Unit of Measure • Real world: Newton
  172. 172. Unit of Measure • Real world: Newton 1 Newton accelerate 1Kg at a rate of 1 m/s2 •
  173. 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. 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. 175. UIDynamicItemBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  176. 176. UIDynamicItemBehavior UIDynamicBehavior UIGravityBehavior UICollisionBehavior UIAttachmentBehavior UISnapBehavior UIPushBehavior UIDynamicItemBehavior
  177. 177. UIDynamicItemBehavior • Customize dynamics properties for items
  178. 178. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity;
  179. 179. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction;
  180. 180. UIDynamicItemBehavior • Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density;
  181. 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. 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. 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. 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. 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. 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. 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. 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. 189. Custom behaviors
  190. 190. Custom Behavior • Can subclass UIDynamicBehavior
  191. 191. Custom Behavior • Can subclass UIDynamicBehavior • add child behavior - (void)addChildBehavior:(UIDynamicBehavior *)behavior; - (void)removeChildBehavior:(UIDynamicBehavior *)behavior; @property (nonatomic, readonly, copy) NSArray* childBehaviors;
  192. 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. 193. Example: gravity & collision
  194. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 210. Action Block • Can define per-step actions
  211. 211. Action Block • Can define per-step actions @property (nonatomic, copy) void (^action)(void);
  212. 212. Action Block • Can define per-step actions @property (nonatomic, copy) void (^action)(void); • UIDynamicAnimator invoke this block in each simulation step
  213. 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. 214. UIDynamicItem protocol
  215. 215. UIDynamicItem Protocol @protocol UIDynamicItem <NSObject> ! @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; ! @end
  216. 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. 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. 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. 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. 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. 221. UIDynamicItem Protocol • center, bounds, and transform are read only once by UIKit
  222. 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. 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. 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. 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. 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. 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. 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. 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. 230. UIDynamicItem Protocol • All items animated by UIKit Dynamics must implement this protocol
  231. 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. 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. 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. 234. Architecture UIDynamicAnimator Reference view UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior View View View
  235. 235. Architecture UIDynamicAnimator Reference view UIDynamicBehavior UIDynamicBehavior UIDynamicBehavior NSObject! <UIDynamicItem> NSObject! <UIDynamicItem> NSObject! <UIDynamicItem>
  236. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 248. Example 1: conform to UIDynamicItem
  249. 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. 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. 251. UIDynamicItem Use Case • Can use a single dynamic item to animate different views
  252. 252. UIDynamicItem Use Case • Can use a single dynamic item to animate different views • Can map center or transform to something else
  253. 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. 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. 255. Example 2: remap center property
  256. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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

×