Date post: | 15-Jan-2015 |
Category: |
Technology |
Upload: | renzo-pretto |
View: | 335 times |
Download: | 0 times |
Renzo G. PrettoiOS Developer
UIKit Dynamics
Who’s talking
Who’s talking
Conference Hashtag
#pragmaconf
Today Agenda
• Introduction and core concepts
Today Agenda
• Introduction and core concepts
•Standard effects: dynamic behaviors
Today Agenda
• Introduction and core concepts
•Standard effects: dynamic behaviors
•Custom effects: custom behaviors
Today Agenda
• Introduction and core concepts
•Standard effects: dynamic behaviors
•Custom effects: custom behaviors
•Advanced concepts
Today Agenda
• Introduction and core concepts
•Standard effects: dynamic behaviors
•Custom effects: custom behaviors
•Advanced concepts
•UIDynamicItem
Today Agenda
• Introduction and core concepts
•Standard effects: dynamic behaviors
•Custom effects: custom behaviors
•Advanced concepts
•UIDynamicItem
•Collection View
Today Agenda
• Introduction and core concepts
•Standard effects: dynamic behaviors
•Custom effects: custom behaviors
•Advanced concepts
•UIDynamicItem
•Collection View
•Conclusion
UIKit Dynamics
UIKit Dynamics
UIKit Dynamics
Architecture
UIDynamicAnimator
Architecture
UIDynamicAnimator
UIDynamicBehavior UIDynamicBehaviorUIDynamicBehavior
Architecture
UIDynamicAnimator
UIDynamicBehavior UIDynamicBehaviorUIDynamicBehavior
Architecture
UIDynamicAnimator
UIDynamicBehavior UIDynamicBehavior
View
UIDynamicBehavior
Architecture
UIDynamicAnimator
UIDynamicBehavior UIDynamicBehavior
View View
UIDynamicBehavior
Architecture
UIDynamicAnimator
UIDynamicBehavior UIDynamicBehavior
View View View
UIDynamicBehavior
Architecture
UIDynamicAnimator Reference view
UIDynamicBehavior UIDynamicBehavior
View View View
UIDynamicBehavior
Architecture
UIDynamicAnimator Reference view
UIDynamicBehavior UIDynamicBehavior
View View View
UIDynamicBehavior
UIDynamicAnimator
UIDynamicAnimator
Reference view
UIDynamicAnimator
•Define the coordinate systemUIDynamicAnimator
Reference view
UIDynamicAnimator
•Define the coordinate system
•Wraps underline engineUIDynamicAnimator
Reference view
UIDynamicAnimator
•Define the coordinate system
•Wraps underline engine
•Keeps track of all the associated behaviors
UIDynamicAnimator
Reference view
UIDynamicAnimator
•Define the coordinate system
•Wraps underline engine
•Keeps track of all the associated behaviors
•Run and optimize the animation
UIDynamicAnimator
Reference view
UIDynamicAnimator
•Define the coordinate system
•Wraps underline engine
•Keeps track of all the associated behaviors
•Run and optimize the animation
•Each dynamic animator is independent from other dynamic animators
UIDynamicAnimator
Reference view
UIDynamicAnimator
•Define the coordinate system
•Wraps underline engine
•Keeps track of all the associated behaviors
•Run and optimize the animation
•Each dynamic animator is independent from other dynamic animators
UIDynamicAnimator *dynamicAnimator; !dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; !dynamicAnimator.delegate = self; ... ![dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...
UIDynamicAnimator
Reference view
UIDynamicAnimator
•Define the coordinate system
•Wraps underline engine
•Keeps track of all the associated behaviors
•Run and optimize the animation
•Each dynamic animator is independent from other dynamic animators
UIDynamicAnimator *dynamicAnimator; !dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; !dynamicAnimator.delegate = self; ... ![dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...
UIDynamicAnimator
Reference view
UIDynamicAnimator
•Define the coordinate system
•Wraps underline engine
•Keeps track of all the associated behaviors
•Run and optimize the animation
•Each dynamic animator is independent from other dynamic animators
UIDynamicAnimator *dynamicAnimator; !dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; !dynamicAnimator.delegate = self; ... ![dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...
UIDynamicAnimator
Reference view
UIDynamicAnimator
•Define the coordinate system
•Wraps underline engine
•Keeps track of all the associated behaviors
•Run and optimize the animation
•Each dynamic animator is independent from other dynamic animators
UIDynamicAnimator *dynamicAnimator; !dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:referenceView]; !dynamicAnimator.delegate = self; ... ![dynamicAnimator addBehavior:firstBehavior]; [dynamicAnimator addBehavior:secondBehavior]; ...
UIDynamicAnimator
Reference view
UIDynamicAnimatorDelegate
@protocol UIDynamicAnimatorDelegate <NSObject> !@optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; !@end
UIDynamicAnimatorDelegate
•Notify pausing and resuming of UIKit Dynamic animator
@protocol UIDynamicAnimatorDelegate <NSObject> !@optional - (void)dynamicAnimatorWillResume:(UIDynamicAnimator*)animator; - (void)dynamicAnimatorDidPause:(UIDynamicAnimator*)animator; !@end
UIDynamicBehaviour
UIDynamicBehavior
UIDynamicBehaviour
•Associated to UIDynamicAnimator
UIDynamicAnimator
UIDynamicBehavior
UIDynamicBehaviour
•Associated to UIDynamicAnimator•Add and remove behaviours to an animator at any times
UIDynamicAnimator
UIDynamicBehavior
UIDynamicBehaviour
•Associated to UIDynamicAnimator•Add and remove behaviours to an animator at any times•Usually associated to a view or a set of view
UIDynamicAnimator
UIDynamicBehavior
View View
UIDynamicBehaviour
•Associated to UIDynamicAnimator•Add and remove behaviours to an animator at any times•Usually associated to a view or a set of view•Composed
UIDynamicAnimator
UIDynamicBehavior
View View UIDynamicBehavior
View
UIDynamicBehaviour
•Associated to UIDynamicAnimator•Add and remove behaviours to an animator at any times•Usually associated to a view or a set of view•Composed•Can be subclassed
UIDynamicAnimator
UIDynamicBehavior
View View UIDynamicBehavior
View
Behaviors Common characteristics
• Initialized with items to animate
Behaviors Common characteristics
• Initialized with items to animate
• Items can be added to behavior at any times
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
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
Primitive behaviors
Default Behaviors
UIDynamicBehavior
Default Behaviors
UIDynamicBehavior
UIGravityBehavior•Gravity
Default Behaviors
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior•Collisions
•Gravity
Default Behaviors
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
•Collisions
•Gravity
•Attachments
Default Behaviors
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
•Collisions
•Gravity
•Attachments
•Snap
Default Behaviors
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
•Collisions
•Gravity
•Attachments
•Snap
•Forces
Default Behaviors
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
•Collisions
•Gravity
•Attachments
•Snap
•Forces
• Item properties
UIGravityBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIGravityBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIGravityBehavior
@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end
UIGravityBehavior
@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end
UIGravityBehavior
@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end
UIGravityBehavior
@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end
UIGravityBehavior
@interface DPGravityViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end @implementation DPGravityViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *items = @[self.greenView]; UIGravityBehavior *gravityBehavior; gravityBehavior = [[UIGravityBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityBehavior]; !} ... @end
UIGravityBehavior
UIGravityBehavior
•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;
UIGravityBehavior
•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;
or@property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
UIGravityBehavior
•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;
or@property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
•Default vector is (0.0, 1.0)(0.0, 1.0)
UIGravityBehavior
•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;
or@property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
•Default vector is (0.0, 1.0)
•Magnitude 1.0 accelerate view to 1000 points/s2 (0.0, 1.0)
UIGravityBehavior
•Defined by a gravity vector@property (readwrite, nonatomic) CGVector gravityDirection;
or@property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
•Default vector is (0.0, 1.0)
•Magnitude 1.0 accelerate view to 1000 points/s2
•Can add and remove items at any time
(0.0, 1.0)
- (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;
UICollisionBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UICollisionBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UICollisionBehavior
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
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
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
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
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
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
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
Collision Boundaries
•Can specify different boundaries
Collision Boundaries
•Can specify different boundaries•Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
Collision Boundaries
•Can specify different boundaries•Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
Collision Boundaries
•Can specify different boundaries•Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
•Segmentes- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
Collision Boundaries
•Can specify different boundaries•Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
•Segmentes- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
•Bezier paths (approximated)- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath;
Collision Boundaries
•Can specify different boundaries•Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
•Segmentes- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
•Bezier paths (approximated)- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath;
Collision Boundaries
•Can specify different boundaries•Reference view
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
• Insets to reference view- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
•Segmentes- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
•Bezier paths (approximated)- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath;
•Boundaries don't have an existence on screen
Collision Mode
•Property collisionmode
Collision Mode
•Property collisionmode@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
Collision Mode
•Property collisionmode@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
• UICollisionBehaviorModeBoundaries
Collision Mode
•Property collisionmode@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
• UICollisionBehaviorModeBoundaries• UICollisionBehaviorModeItems
Collision Mode
•Property collisionmode@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
• UICollisionBehaviorModeBoundaries• UICollisionBehaviorModeItems
• UICollisionBehaviorModeEverything (default)
Tips
Tips
•Can use multiple collision behaviors
Tips
•Can use multiple collision behaviors
•Add and remove items to this behaviour anytime - (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;
Tips
•Can use multiple collision behaviors
•Add and remove items to this behaviour anytime
•Collision detection have CPU cost
- (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;
•Methods that inform collision start / end between view
UICollisionBehaviorDelegate
•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
UICollisionBehaviorDelegate
•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
•Methods that inform collision start /end between boundaries
UICollisionBehaviorDelegate
•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
•Methods that inform collision start /end between boundaries- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier;
UICollisionBehaviorDelegate
•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
•Methods that inform collision start /end between boundaries- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier;
UICollisionBehaviorDelegate
•Methods that inform collision start / end between view- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
•Methods that inform collision start /end between boundaries- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier;!•Reference view has nil identifier
UICollisionBehaviorDelegate
UIAttachmentBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIAttachmentBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIAttachmentBehavior
UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
UIAttachmentBehavior@interface DPAttachmentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *redView; @property (weak, nonatomic) IBOutlet UIView *greenView; @property (strong, nonatomic) UIDynamicAnimator *animator; @end !@implementation DPAttachmentViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIAttachmentBehavior *attachmentBehavior; attachmentBehavior =[[UIAttachmentBehavior alloc] initWithItem:self.greenView attachedToItem:self.redView]; [self.animator addBehavior:attachmentBehavior]; } !- (IBAction)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer { ! CGPoint anchorPoint = [gestureRecognizer locationInView:self.view]; self.redView.center = anchorPoint; [self.animator updateItemUsingCurrentState:self.redView]; } ... @end
UIAttachmentBehavior
UIAttachmentBehavior
•View connected to an attachment point
UIAttachmentBehavior
•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
UIAttachmentBehavior
•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
•Two views connected together
UIAttachmentBehavior
•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
•Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;
UIAttachmentBehavior
•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
•Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;
•Specify connection point offset
UIAttachmentBehavior
•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
•Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;
•Specify connection point offset - (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point;
UIAttachmentBehavior
•View connected to an attachment point - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
•Two views connected together - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;
•Specify connection point offset - (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point;
- (instancetype)initWithItem:(id <UIDynamicItem>)item1 offsetFromCenter:(UIOffset)offset1 attachedToItem:(id <UIDynamicItem>)item2 offsetFromCenter:(UIOffset)offset2;
UIAttachmentBehavior
Springs
•Springs
Springs
•Springs @property (readwrite, nonatomic) CGFloat damping;
Springs
•Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
Springs
•Springs @property (readwrite, nonatomic) CGFloat damping; @property (readwrite, nonatomic) CGFloat frequency;
UISnapBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UISnapBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UISnapBehavior
UISnapBehavior
UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
UISnapBehaviorinterface DPSnapViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @property (weak, nonatomic) IBOutlet UIView *greenView; @end !@implementation DPSnapViewController ... - (void)viewDidLoad { [super viewDidLoad]; ! self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } !- (IBAction)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer { ! CGPoint snapPoint = [gestureRecognizer locationInView:self.view]; if (nil != self.snapBehavior) { [self.dynamicAnimator removeBehavior:self.snapBehavior]; } self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.greenView snapToPoint:snapPoint]; [self.animator addBehavior:self.snapBehavior]; } ... @end
UISnapBehavior
•Snap view in place in non rotated state
UISnapBehavior
•Snap view in place in non rotated state- (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;
UISnapBehavior
•Snap view in place in non rotated state- (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;
•Customize the dumping effects
UISnapBehavior
•Snap view in place in non rotated state- (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point;
•Customize the dumping effects @property (nonatomic, assign) CGFloat damping;
UIPushBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIPushBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIPushBehavior
~F = m ~a
UIPushBehavior
~F = m ~a
UIPushBehavior
• , apply force to views: ~F = m ~a
UIPushBehavior
• , apply force to views: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
~F = m ~a
UIPushBehavior
• , apply force to views: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
•Force vector expressed in two way:
~F = m ~a
UIPushBehavior
• , apply force to views: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
•Force vector expressed in two way: @property (readwrite, nonatomic) CGVector pushDirection;
~F = m ~a
UIPushBehavior
• , apply force to views: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
•Force vector expressed in two way: @property (readwrite, nonatomic) CGVector pushDirection;
or @property (readwrite, nonatomic) CGFloat angle; @property (readwrite, nonatomic) CGFloat magnitude;
~F = m ~a
UIPushBehavior
•Customize where apply this force in the view
UIPushBehavior
•Customize where apply this force in the view
UIPushBehavior
•Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
UIPushBehavior
•Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
UIPushBehavior
•Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
UIPushBehavior
•Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
•Can add and remove items at any time
UIPushBehavior
•Customize where apply this force in the view - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
•Can add and remove items at any time- (void)addItem:(id <UIDynamicItem>)item; - (void)removeItem:(id <UIDynamicItem>)item;
UIPushBehavior Mode
•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
UIPushBehavior Mode
•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
• UIPushBehaviorModeContinuous
UIPushBehavior Mode
•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
• UIPushBehaviorModeContinuous • force still be applied while behaviour is active
UIPushBehavior Mode
•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
• UIPushBehaviorModeContinuous • force still be applied while behaviour is active
• views accelerate
UIPushBehavior Mode
•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
• UIPushBehaviorModeContinuous • force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous
UIPushBehavior Mode
•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
• UIPushBehaviorModeContinuous • force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous• apply a very quick impulse
UIPushBehavior Mode
•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
• UIPushBehaviorModeContinuous • force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous• apply a very quick impulse
• view immediately acquire velocity (no acceleration)
UIPushBehavior Mode
•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
• UIPushBehaviorModeContinuous • force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous• apply a very quick impulse
• view immediately acquire velocity (no acceleration)
• automatically disable itself after applying it
UIPushBehavior Mode
•Different mode to apply forces: - (instancetype)initWithItems:(NSArray *)items mode:(UIPushBehaviorMode)mode;
• UIPushBehaviorModeContinuous • force still be applied while behaviour is active
• views accelerate
•UIPushBehaviorModeInstantaneous• apply a very quick impulse
• view immediately acquire velocity (no acceleration)
• automatically disable itself after applying it
• to re-enable: @property (nonatomic, readwrite) BOOL active;
UIPushBehavior Mode
Example: force comparison
~F = m ~a
~a =~F
m
Example: gravity comparison
Feel The Force!
Feel The Force!
•Gravity
Feel The Force!
•Gravity
• views accelerate with the same rate
Feel The Force!
•Gravity
• views accelerate with the same rate
•Push behavior in continuos mode
Feel The Force!
•Gravity
• views accelerate with the same rate
•Push behavior in continuos mode
• the smaller views accelerate more
Feel The Force!
•Gravity
• views accelerate with the same rate
•Push behavior in continuos mode
• the smaller views accelerate more
•Push behavior in instantaneous mode
Feel The Force!
•Gravity
• views accelerate with the same rate
•Push behavior in continuos mode
• the smaller views accelerate more
•Push behavior in instantaneous mode
• view acquire velocity and then the velocity doesn’t change
Feel The Force!
•Gravity
• views accelerate with the same rate
•Push behavior in continuos mode
• the smaller views accelerate more
•Push behavior in instantaneous mode
• view acquire velocity and then the velocity doesn’t change
• the smaller views acquire more velocity
Unit of Measure
•Real world: Newton
Unit of Measure
•Real world: Newton
• 1 Newton accelerate 1Kg at a rate of 1 m/s2
Unit of Measure
•Real world: Newton
• 1 Newton accelerate 1Kg at a rate of 1 m/s2
•UIKit:
• magnitude of 1.0 accelerate 100x100 point view to 100 points/s2
Unit of Measure
•Real world: Newton
• 1 Newton accelerate 1Kg at a rate of 1 m/s2
•UIKit:
• magnitude of 1.0 accelerate 100x100 point view to 100 points/s2
• “UIKit Newton”
UIDynamicItemBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
UIDynamicItemBehavior
UIDynamicBehavior
UIGravityBehavior
UICollisionBehavior
UIAttachmentBehavior
UISnapBehavior
UIPushBehavior
UIDynamicItemBehavior
•Customize dynamics properties for items
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity;
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction;
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density;
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance;
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance;
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;
•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;
•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;
•Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;
•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;
•Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;
•Can add and remove items at any time
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;
•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;
•Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;
•Can add and remove items at any time
UIDynamicItemBehavior
•Customize dynamics properties for items @property (readwrite, nonatomic) CGFloat elasticity; @property (readwrite, nonatomic) CGFloat friction; @property (readwrite, nonatomic) CGFloat density; @property (readwrite, nonatomic) CGFloat resistance; @property (readwrite, nonatomic) CGFloat angularResistance; @property (readwrite, nonatomic) BOOL allowsRotation;
•Add linear velocity (points per second)- (void)addLinearVelocity:(CGPoint)velocity forItem:(id <UIDynamicItem>)item;- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;
•Add angular velocity (radians per second) - (void)addAngularVelocity:(CGFloat)velocity forItem:(id <UIDynamicItem>)item; - (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;
•Can add and remove items at any time
UIDynamicItemBehavior
Custom behaviors
Custom Behavior
•Can subclass UIDynamicBehavior
Custom Behavior
•Can subclass UIDynamicBehavior
• add child behavior - (void)addChildBehavior:(UIDynamicBehavior *)behavior; - (void)removeChildBehavior:(UIDynamicBehavior *)behavior;
@property (nonatomic, readonly, copy) NSArray* childBehaviors;
Custom Behavior
•Can subclass UIDynamicBehavior
• add child behavior - (void)addChildBehavior:(UIDynamicBehavior *)behavior; - (void)removeChildBehavior:(UIDynamicBehavior *)behavior;
@property (nonatomic, readonly, copy) NSArray* childBehaviors;
•No CPU cost or any runtime difference
Example: gravity & collision
Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end
Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end
Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end
Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end
Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll]; } !@end
@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end
Example: gravity & collision
@interface DPGravityCollisionBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray *)items; @end !!@implementation DPGravityCollisionBehavior !- (instancetype)initWithItems:(NSArray *)items { self = [super init]; if (self) { UIGravityBehavior *gravity; UICollisionBehavior *collision; ! gravity =[[UIGravityBehavior alloc] initWithItems:items]; collision = [[UICollisionBehavior alloc] initWithItems:items]; collision.translatesReferenceBoundsIntoBoundary = YES; [self addChildBehavior:gravity]; [self addChildBehavior:collision]; ! } return self; } !@end
Example: gravity & collision
Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; !!!!!! ! } !@end
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items]; UICollisionBehavior *coll = [[UICollisionBehavior alloc] initWithItems:items]; coll.translatesReferenceBoundsIntoBoundary = YES; ! [self.animator addBehavior:gravity]; [self.animator addBehavior:coll];
Example: gravity & collision@interface DPGravityCollisionViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator *animator; @end !!@implementation DPGravityCollisionViewController !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; self.animator.delegate = self; NSArray *items = @[...]; !!!!!! ! } !@end
DPGravityCollisionBehavior *gravityAndCollision; gravityAndCollision= [[DPGravityCollisionBehavior alloc] initWithItems:items]; ! [self.animator addBehavior:gravityAndCollision];
Action Block
•Can define per-step actions
Action Block
•Can define per-step actions @property (nonatomic, copy) void (^action)(void);
Action Block
•Can define per-step actions @property (nonatomic, copy) void (^action)(void);
• UIDynamicAnimator invoke this block in each simulation step
Action Block
•Can define per-step actions @property (nonatomic, copy) void (^action)(void);
• UIDynamicAnimator invoke this block in each simulation step
•So performance are crucial
UIDynamicItem protocol
UIDynamicItem Protocol@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end
UIDynamicItem Protocol
•All items animated by UIKit Dynamics must implement this protocol
@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end
UIDynamicItem Protocol
•All items animated by UIKit Dynamics must implement this protocol
•Describe what UIKit Dynamics needs to animate an item
@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end
UIDynamicItem Protocol
•All items animated by UIKit Dynamics must implement this protocol
•Describe what UIKit Dynamics needs to animate an item
•position: center
@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end
UIDynamicItem Protocol
•All items animated by UIKit Dynamics must implement this protocol
•Describe what UIKit Dynamics needs to animate an item
•position: center
• size: bounds
@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end
UIDynamicItem Protocol
•All items animated by UIKit Dynamics must implement this protocol
•Describe what UIKit Dynamics needs to animate an item
•position: center
• size: bounds
• angle: transform (only 2D-transform)
@protocol UIDynamicItem <NSObject> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
• center and transform are set on every animation tick
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
• center and transform are set on every animation tick • methods performances are critical
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
• center and transform are set on every animation tick • methods performances are critical
•After grab the initial state every external change to center, bounds, and transform will be ignored
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
• center and transform are set on every animation tick • methods performances are critical
•After grab the initial state every external change to center, bounds, and transform will be ignored
•A dynamic item should always have a valid initial state
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
• center and transform are set on every animation tick • methods performances are critical
•After grab the initial state every external change to center, bounds, and transform will be ignored
•A dynamic item should always have a valid initial state• need a size
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
• center and transform are set on every animation tick • methods performances are critical
•After grab the initial state every external change to center, bounds, and transform will be ignored
•A dynamic item should always have a valid initial state• need a size
• need a reasonable position
UIDynamicItem Protocol
• center, bounds, and transform are read only once by UIKit • When adding the item to an animator for the first time
• center and transform are set on every animation tick • methods performances are critical
•After grab the initial state every external change to center, bounds, and transform will be ignored
•A dynamic item should always have a valid initial state• need a size
• need a reasonable position
UIDynamicItem Protocol
•All items animated by UIKit Dynamics must implement this protocol
UIDynamicItem Protocol
•All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol@interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... }
UIDynamicItem Protocol
•All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol@interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... }
• UICollectionViewLayoutAttributes conforms to protocol@interface UICollectionViewLayoutAttributes : NSObject < NSCopying, UIDynamicItem > { ... }
UIDynamicItem Protocol
•All items animated by UIKit Dynamics must implement this protocol • UIView conforms to protocol@interface UIView : UIResponder < NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem > { ... }
• UICollectionViewLayoutAttributes conforms to protocol@interface UICollectionViewLayoutAttributes : NSObject < NSCopying, UIDynamicItem > { ... }
•Custom class can conform to protocol@interface DPDynamicObject : NSObject < UIDynamicItem > { ... }
Architecture
UIDynamicAnimator Reference view
UIDynamicBehavior UIDynamicBehavior
View View View
UIDynamicBehavior
Architecture
UIDynamicAnimator Reference view
UIDynamicBehavior UIDynamicBehaviorUIDynamicBehavior
NSObject!<UIDynamicItem>
NSObject!<UIDynamicItem>
NSObject!<UIDynamicItem>
@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end
Example 1: conform to UIDynamicItem
@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end
Example 1: conform to UIDynamicItem
@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end
Example 1: conform to UIDynamicItem
@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end
Example 1: conform to UIDynamicItem
@interface DPDynamicObject : NSObject <UIDynamicItem> !@property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGAffineTransform transform; !@end !!@implementation DPDynamicObject !- (CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } !- (CGPoint)center { return CGPointMake(50.0, 50.0); } !- (void)setCenter:(CGPoint)center { NSLog(@"Center = %@", NSStringFromCGPoint(center)); } !- (CGAffineTransform)transform { return CGAffineTransformIdentity; } !- (void)setTransform:(CGAffineTransform)transform { NSLog(@"Transform = %@", NSStringFromCGAffineTransform(transform)); } !@end
Example 1: conform to UIDynamicItem
Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
Example 1: conform to UIDynamicItem@interface DPDynamicItemProtocolViewController : UIViewController @property (strong, nonatomic) UIDynamicAnimator * animator; @property (strong, nonatomic) DPDynamicObject *dynamicObject; @end !@implementation DPDynamicItemProtocolViewController ... !- (void)viewDidLoad { [super viewDidLoad]; self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; ! self.dynamicObject = [[DPDynamicObject alloc] init]; ! UIGravityBehavior *g; g =[[UIGravityBehavior alloc] initWithItems: @[self.dynamicObject] ]; UIDynamicItemBehavior *b; b =[[UIDynamicItemBehavior alloc] initWithItems: @[self.dynamicObject] ]; b.elasticity = 0.5f; UICollisionBehavior *c; c =[[UICollisionBehavior alloc] initWithItems: @[self.dynamicObject] ]; c.translatesReferenceBoundsIntoBoundary = YES; [self.animator addBehavior:g]; [self.animator addBehavior:b]; [self.animator addBehavior:c]; } ... @end
Example 1: conform to UIDynamicItem
Example 1: conform to UIDynamicItem
2013-10-17 18:58:05.598 DynamicsPlayground[771:60b] Animator is running 2013-10-17 18:58:05.609 DynamicsPlayground[771:60b] Center = {50, 50.04797} 2013-10-17 18:58:05.611 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.626 DynamicsPlayground[771:60b] Center = {50, 50.447464} 2013-10-17 18:58:05.629 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.642 DynamicsPlayground[771:60b] Center = {50, 51.054173} 2013-10-17 18:58:05.645 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.659 DynamicsPlayground[771:60b] Center = {50, 51.915657} 2013-10-17 18:58:05.661 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.675 DynamicsPlayground[771:60b] Center = {50, 53.031506} 2013-10-17 18:58:05.677 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] !... !2013-10-17 18:58:08.742 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.744 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.759 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.761 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.775 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.777 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.792 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.794 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.809 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.810 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.812 DynamicsPlayground[771:60b] Animator is stopped
Example 1: conform to UIDynamicItem
2013-10-17 18:58:05.598 DynamicsPlayground[771:60b] Animator is running 2013-10-17 18:58:05.609 DynamicsPlayground[771:60b] Center = {50, 50.04797} 2013-10-17 18:58:05.611 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.626 DynamicsPlayground[771:60b] Center = {50, 50.447464} 2013-10-17 18:58:05.629 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.642 DynamicsPlayground[771:60b] Center = {50, 51.054173} 2013-10-17 18:58:05.645 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.659 DynamicsPlayground[771:60b] Center = {50, 51.915657} 2013-10-17 18:58:05.661 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:05.675 DynamicsPlayground[771:60b] Center = {50, 53.031506} 2013-10-17 18:58:05.677 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] !... !2013-10-17 18:58:08.742 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.744 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.759 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.761 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.775 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.777 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.792 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.794 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.809 DynamicsPlayground[771:60b] Center = {50, 518.13135} 2013-10-17 18:58:08.810 DynamicsPlayground[771:60b] Transform = [1, 0, -0, 1, 0, 0] 2013-10-17 18:58:08.812 DynamicsPlayground[771:60b] Animator is stopped
•Can use a single dynamic item to animate different views
UIDynamicItem Use Case
•Can use a single dynamic item to animate different views
•Can map center or transform to something else
UIDynamicItem Use Case
•Can use a single dynamic item to animate different views
•Can map center or transform to something else
•To “animate” something that isn’t a view or a collection view use a UIDynamicItem
UIDynamicItem Use Case
•Can use a single dynamic item to animate different views
•Can map center or transform to something else
•To “animate” something that isn’t a view or a collection view use a UIDynamicItem
UIDynamicItem Use Case
Example 2: remap center property
Example 2: remap center property
@protocol ResizableDynamicItem <UIDynamicItem> !!@interface APLPositionToBoundsMapping : NSObject <UIDynamicItem> !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target; !@end !!@protocol ResizableDynamicItem <UIDynamicItem> !@property (nonatomic, readwrite) CGRect bounds; !@end
Example 2: remap center property
@protocol ResizableDynamicItem <UIDynamicItem> !!@interface APLPositionToBoundsMapping : NSObject <UIDynamicItem> !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target; !@end !!@protocol ResizableDynamicItem <UIDynamicItem> !@property (nonatomic, readwrite) CGRect bounds; !@end
Example 2: remap center property
@protocol ResizableDynamicItem <UIDynamicItem> !!@interface APLPositionToBoundsMapping : NSObject <UIDynamicItem> !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target; !@end !!@protocol ResizableDynamicItem <UIDynamicItem> !@property (nonatomic, readwrite) CGRect bounds; !@end
Example 2: remap center property#import "APLPositionToBoundsMapping.h" !@interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end !@implementation APLPositionToBoundsMapping !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } !- (CGRect)bounds { return self.target.bounds; // Pass through } !- (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } !- (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } !- (CGAffineTransform)transform { return self.target.transform; // Pass through } !- (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end
Example 2: remap center property#import "APLPositionToBoundsMapping.h" !@interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end !@implementation APLPositionToBoundsMapping !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } !- (CGRect)bounds { return self.target.bounds; // Pass through } !- (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } !- (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } !- (CGAffineTransform)transform { return self.target.transform; // Pass through } !- (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end
Example 2: remap center property#import "APLPositionToBoundsMapping.h" !@interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end !@implementation APLPositionToBoundsMapping !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } !- (CGRect)bounds { return self.target.bounds; // Pass through } !- (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } !- (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } !- (CGAffineTransform)transform { return self.target.transform; // Pass through } !- (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end
Example 2: remap center property#import "APLPositionToBoundsMapping.h" !@interface APLPositionToBoundsMapping () @property (nonatomic, strong) id<ResizableDynamicItem> target; @end !@implementation APLPositionToBoundsMapping !- (instancetype)initWithTarget:(id<ResizableDynamicItem>)target { if ((self = [super init])) { _target = target; } return self; } !- (CGRect)bounds { return self.target.bounds; // Pass through } !- (CGPoint)center { return CGPointMake(self.target.bounds.size.width, self.target.bounds.size.height); } !- (void)setCenter:(CGPoint)center { self.target.bounds = CGRectMake(0, 0, center.x, center.y); } !- (CGAffineTransform)transform { return self.target.transform; // Pass through } !- (void)setTransform:(CGAffineTransform)transform { self.target.transform = transform; // Pass through } @end
Example 2: remap center property@import UIKit; !!@interface APLCustomDynamicItemViewController : UIViewController @end !!@interface APLCustomDynamicItemViewController () @property (nonatomic, weak) IBOutlet UIButton *button1; @property (nonatomic, readwrite) CGRect button1Bounds; @property (nonatomic, strong) UIDynamicAnimator *animator; @end !!@implementation APLCustomDynamicItemViewController !- (void)viewDidLoad { ! // Save the button's initial bounds. self.button1Bounds = self.button1.bounds; // Force the button image to scale with its bounds. self.button1.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; self.button1.contentVerticalAlignment = UIControlContentHorizontalAlignmentFill; } !// ... continue !@end
Example 2: remap center property@import UIKit; !!@interface APLCustomDynamicItemViewController : UIViewController @end !!@interface APLCustomDynamicItemViewController () @property (nonatomic, weak) IBOutlet UIButton *button1; @property (nonatomic, readwrite) CGRect button1Bounds; @property (nonatomic, strong) UIDynamicAnimator *animator; @end !!@implementation APLCustomDynamicItemViewController !- (void)viewDidLoad { ! // Save the button's initial bounds. self.button1Bounds = self.button1.bounds; // Force the button image to scale with its bounds. self.button1.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; self.button1.contentVerticalAlignment = UIControlContentHorizontalAlignmentFill; } !// ... continue !@end
Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end
Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end
Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end
Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end
Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end
Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end
Example 2: remap center property!@implementation APLCustomDynamicItemViewController !... !- (IBAction)buttonAction:(id)sender { ! // Reset the buttons bounds to their initial state. self.button1.bounds = self.button1Bounds; UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; APLPositionToBoundsMapping *buttonBoundsDynamicItem; buttonBoundsDynamicItem =[[APLPositionToBoundsMapping alloc] initWithTarget:sender]; ! UIAttachmentBehavior *attachment; attachment = [[UIAttachmentBehavior alloc] initWithItem:buttonBoundsDynamicItem attachedToAnchor:buttonBoundsDynamicItem.center]; [attachment setFrequency:2.0]; [attachment setDamping:0.3]; [animator addBehavior:attachment]; UIPushBehavior *pushBehavior; pushBehavior = [[UIPushBehavior alloc] initWithItems:@[buttonBoundsDynamicItem] mode:UIPushBehaviorModeInstantaneous]; pushBehavior.angle = M_PI_4; pushBehavior.magnitude = 2.0; ! [animator addBehavior:pushBehavior]; self.animator = animator; } @end
Example 2: remap center property
19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped
Example 2: remap center property
19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped
Example 2: remap center property
19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped
Example 2: remap center property
19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped
Example 2: remap center property
19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped
Example 2: remap center property
19:18:56.545 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.547 -[APLPositionToBoundsMapping center]:68 {150, 46} 19:18:56.549 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.550 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.551 -[APLPositionToBoundsMapping bounds]:55 {{0, 0}, {150, 46}} 19:18:56.552 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.553 -[APLPositionToBoundsMapping transform]:94 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.556 Animator is running 19:18:56.561 -[APLPositionToBoundsMapping setCenter:]:81 {150, 45.999996} 19:18:56.563 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3833854e-06, 1.3833854e-06, 1, 0, 0] 19:18:56.575 -[APLPositionToBoundsMapping setCenter:]:81 {153.80513, 49.805138} 19:18:56.578 -[APLPositionToBoundsMapping setTransform:]:107 [1, -1.3838192e-06, 1.3838192e-06, 1, 0, 0] !... !19:19:02.527 -[APLPositionToBoundsMapping setCenter:]:81 {150.07957, 46.079357} 19:19:02.529 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7647307e-06, 2.7647307e-06, 1, 0, 0] 19:19:02.542 -[APLPositionToBoundsMapping setCenter:]:81 {150.07266, 46.072491} 19:19:02.545 -[APLPositionToBoundsMapping setTransform:]:107 [1, -2.7667704e-06, 2.7667704e-06, 1, 0, 0] 19:19:02.547 Animator stopped
Example 2: remap center property
Dynamics & Collection View
Dynamics & UICollectionViews
• UICollectionViewLayoutAttributes conform to UIDynamicItem
Dynamics & UICollectionViews
• UICollectionViewLayoutAttributes conform to UIDynamicItem
•Can use UIKit Dynamics with collection view
Dynamics & UICollectionViews
• UICollectionViewLayoutAttributes conform to UIDynamicItem
•Can use UIKit Dynamics with collection view
• How
Dynamics & UICollectionViews
• UICollectionViewLayoutAttributes conform to UIDynamicItem
•Can use UIKit Dynamics with collection view
• How
•Use UIKit Dynamics for very specific animations
Dynamics & UICollectionViews
• UICollectionViewLayoutAttributes conform to UIDynamicItem
•Can use UIKit Dynamics with collection view
• How
•Use UIKit Dynamics for very specific animations
• create UIDynamicAnimator as needed and discard later
Dynamics & UICollectionViews
• UICollectionViewLayoutAttributes conform to UIDynamicItem
•Can use UIKit Dynamics with collection view
• How
•Use UIKit Dynamics for very specific animations
• create UIDynamicAnimator as needed and discard later
•Animate a subset of a layout
Dynamics & UICollectionViews
• UICollectionViewLayoutAttributes conform to UIDynamicItem
•Can use UIKit Dynamics with collection view
• How
•Use UIKit Dynamics for very specific animations
• create UIDynamicAnimator as needed and discard later
•Animate a subset of a layout
•Build an entire layout with UIKit Dynamics
Dynamics & UICollectionViews
• UICollectionViewLayoutAttributes conform to UIDynamicItem
•Can use UIKit Dynamics with collection view
• How
•Use UIKit Dynamics for very specific animations
• create UIDynamicAnimator as needed and discard later
•Animate a subset of a layout
•Build an entire layout with UIKit Dynamics
•performace: better for small data source
Basic steps
•Create the the UICollectionViewLayout instance
Basic steps
•Create the the UICollectionViewLayout instance
•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;
animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
Basic steps
•Create the the UICollectionViewLayout instance
•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;
animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
Basic steps
•Create the the UICollectionViewLayout instance
•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;
animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
Basic steps
•Create the the UICollectionViewLayout instance
•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;
animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
Basic steps
•Create the the UICollectionViewLayout instance
•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;
animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
• Create behaviors and add UICollectionViewLayoutAttributes to these behaviors
Basic steps
•Create the the UICollectionViewLayout instance
•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;
animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
• Create behaviors and add UICollectionViewLayoutAttributes to these behaviors UICollectionViewLayoutAttributes *attribute = ...;
UIAttachmentBehavior *spring;
spring = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:anchorPoint];
...
Basic steps
•Create the the UICollectionViewLayout instance
•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;
animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
• Create behaviors and add UICollectionViewLayoutAttributes to these behaviors UICollectionViewLayoutAttributes *attribute = ...;
UIAttachmentBehavior *spring;
spring = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:anchorPoint];
...
Basic steps
•Create the the UICollectionViewLayout instance
•Create the UIDynamicAnimator with layout instance UICollectionViewLayout *layout = ...;
animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout :layout];
• Create behaviors and add UICollectionViewLayoutAttributes to these behaviors UICollectionViewLayoutAttributes *attribute = ...;
UIAttachmentBehavior *spring;
spring = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:anchorPoint];
...
UIKit Dynamics Support for UICollectionViews
Dynamics has convenience support for UICollectionView
UIKit Dynamics Support for UICollectionViews
Dynamics has convenience support for UICollectionView
•Dynamics automatically invalidate layout as needed
UIKit Dynamics Support for UICollectionViews
Dynamics has convenience support for UICollectionView
•Dynamics automatically invalidate layout as needed
•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView
UIKit Dynamics Support for UICollectionViews
Dynamics has convenience support for UICollectionView
•Dynamics automatically invalidate layout as needed
•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView
• UIDynamicAnimator provide convenience method to implement custom layout
UIKit Dynamics Support for UICollectionViews
Dynamics has convenience support for UICollectionView
•Dynamics automatically invalidate layout as needed
•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView
• UIDynamicAnimator provide convenience method to implement custom layout- (UICollectionViewLayoutAttributes*)layoutAttributesForCellAtIndexPath:(NSIndexPath*)ip;
UIKit Dynamics Support for UICollectionViews
Dynamics has convenience support for UICollectionView
•Dynamics automatically invalidate layout as needed
•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView
• UIDynamicAnimator provide convenience method to implement custom layout- (UICollectionViewLayoutAttributes*)layoutAttributesForCellAtIndexPath:(NSIndexPath*)ip;
- (UICollectionViewLayoutAttributes*)layoutAttributesForSupplementaryViewOfKind:(NSString *)k atIndexPath:(NSIndexPath *)ip;
UIKit Dynamics Support for UICollectionViews
Dynamics has convenience support for UICollectionView
•Dynamics automatically invalidate layout as needed
•Dynamics pause the animator when a UICollectionViewLayout is no longer associated with the UICollectionView
• UIDynamicAnimator provide convenience method to implement custom layout- (UICollectionViewLayoutAttributes*)layoutAttributesForCellAtIndexPath:(NSIndexPath*)ip;
- (UICollectionViewLayoutAttributes*)layoutAttributesForSupplementaryViewOfKind:(NSString *)k atIndexPath:(NSIndexPath *)ip;
- (UICollectionViewLayoutAttributes*)layoutAttributesForDecorationViewOfKind:(NSString*)k atIndexPath:(NSIndexPath *)ip;
Collection View Layout Updates
Use usual UICollectionViewLayout methods for layout update:
Collection View Layout Updates
Use usual UICollectionViewLayout methods for layout update: • prepareLayout
Collection View Layout Updates
Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state
Collection View Layout Updates
Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state
•prepareForCollectionViewUpdates
Collection View Layout Updates
Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state
•prepareForCollectionViewUpdates
•opportunity to add UICollectionViewLayoutAttributes to behaviors.
Collection View Layout Updates
Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state
•prepareForCollectionViewUpdates
•opportunity to add UICollectionViewLayoutAttributes to behaviors.
• layoutAttributesForElementsInRect
Collection View Layout Updates
Use usual UICollectionViewLayout methods for layout update: • prepareLayout •used when instantiate an animator or create initial state
•prepareForCollectionViewUpdates
•opportunity to add UICollectionViewLayoutAttributes to behaviors.
• layoutAttributesForElementsInRect • UIDynamicAnimator has itemsInRect
Example: collection view
Example: collection view
@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end
Example: collection view
@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end
Example: collection view
@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end
Example: collection view
@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end
Example: collection view
@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end
Example: collection view
@interface DPProportionalSpringFlowLayout : UICollectionViewFlowLayout @end !!!@interface DPProportionalSpringFlowLayout () !@property (strong, readwrite, nonatomic) UIDynamicAnimator *dynamicAnimator; !@end !@implementation DPProportionalSpringFlowLayout !- (CGSize)itemSize { return CGSizeMake(CGRectGetWidth(self.collectionView.frame), 50.0f); } !- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return [self.dynamicAnimator itemsInRect:rect]; } !- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self.dynamicAnimator layoutAttributesForCellAtIndexPath:indexPath]; } !... // continue !@end
Example: collection view
@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end
Example: collection view
@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end
Example: collection view
@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end
Example: collection view
@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end
Example: collection view
@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end
Example: collection view
@implementation DPProportionalSpringFlowLayout !// ... continue from previous slide !- (void)prepareLayout { [super prepareLayout]; ! if (nil == [self dynamicAnimator]) { ! self.dynamicAnimator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self]; ! CGSize contentSize = [self collectionViewContentSize]; CGRect contentRect = { CGPointZero, contentSize }; NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:contentRect]; // create spring behavior for each item for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) { ! UIAttachmentBehavior *springBehavior; springBehavior = [[UIAttachmentBehavior alloc] initWithItem:attribute attachedToAnchor:[attribute center]]; springBehavior.length = 0.0; springBehavior.damping = 0.5; springBehavior.frequency = 0.8; [self.dynamicAnimator addBehavior:springBehavior]; } } } !// ... continue !@end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@implementation DPProportionalSpringFlowLayout // ... continue form previous slide !- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { UIScrollView *scrollView = [self collectionView]; CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y; CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; for (UIAttachmentBehavior *springBehavior in [self.dynamicAnimator behaviors]) { CGPoint anchorPoint = [springBehavior anchorPoint]; CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y); CGFloat scrollResistance = distanceFromTouch / 500.0f; ! UICollectionViewLayoutAttributes *attribute = [springBehavior.items firstObject]; CGPoint center = [attribute center]; CGFloat springStretch = scrollDelta * scrollResistance; if (scroll > 0) { center.y += MIN(scrollDelta, scrollDelta * springStretch); } else { center.y += MAX(scrollDelta, scrollDelta * springStretch); } ! attribute.center = center; [self.dynamicAnimator updateItemUsingCurrentState:attribute]; } return NO; } @end
Example: collection view
@import UIKit; !@interface DPDynamicCollectionViewViewController : UIViewController @end !!!!!const NSInteger kCellCount = 20; !@interface DPDynamicCollectionViewViewController() <UICollectionViewDataSource, UICollectionViewDelegate> ! @property (weak, nonatomic) IBOutlet UICollectionView *collectionView; ! @property (strong, nonatomic) UICollectionViewFlowLayout *flowLayout; ! @property (strong, nonatomic) NSMutableArray *colors; !@end !!
Example: collection view
@import UIKit; !@interface DPDynamicCollectionViewViewController : UIViewController @end !!!!!const NSInteger kCellCount = 20; !@interface DPDynamicCollectionViewViewController() <UICollectionViewDataSource, UICollectionViewDelegate> ! @property (weak, nonatomic) IBOutlet UICollectionView *collectionView; ! @property (strong, nonatomic) UICollectionViewFlowLayout *flowLayout; ! @property (strong, nonatomic) NSMutableArray *colors; !@end !!
Example: collection view
@import UIKit; !@interface DPDynamicCollectionViewViewController : UIViewController @end !!!!!const NSInteger kCellCount = 20; !@interface DPDynamicCollectionViewViewController() <UICollectionViewDataSource, UICollectionViewDelegate> ! @property (weak, nonatomic) IBOutlet UICollectionView *collectionView; ! @property (strong, nonatomic) UICollectionViewFlowLayout *flowLayout; ! @property (strong, nonatomic) NSMutableArray *colors; !@end !!
Example: collection view
@implementation DPDynamicCollectionViewViewController !... !- (void)viewDidLoad { [super viewDidLoad]; ! self.colors = [self cellColors]; ! [self.collectionView registerClass:[DPCollectionViewCell class] forCellWithReuseIdentifier:[DPCollectionViewCell cellIdentifier]]; self.flowLayout = [[DPProportionalSpringFlowLayout alloc] init]; [self.collectionView setCollectionViewLayout:[self flowLayout]]; !} !// ... continue !!!!@end
Example: collection view
@implementation DPDynamicCollectionViewViewController !... !- (void)viewDidLoad { [super viewDidLoad]; ! self.colors = [self cellColors]; ! [self.collectionView registerClass:[DPCollectionViewCell class] forCellWithReuseIdentifier:[DPCollectionViewCell cellIdentifier]]; self.flowLayout = [[DPProportionalSpringFlowLayout alloc] init]; [self.collectionView setCollectionViewLayout:[self flowLayout]]; !} !// ... continue !!!!@end
Example: collection view
@implementation DPDynamicCollectionViewViewController !... !- (void)viewDidLoad { [super viewDidLoad]; ! self.colors = [self cellColors]; ! [self.collectionView registerClass:[DPCollectionViewCell class] forCellWithReuseIdentifier:[DPCollectionViewCell cellIdentifier]]; self.flowLayout = [[DPProportionalSpringFlowLayout alloc] init]; [self.collectionView setCollectionViewLayout:[self flowLayout]]; !} !// ... continue !!!!@end
Example: collection view
@implementation DPDynamicCollectionViewViewController !// ... continue form previous slide !!- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return kCellCount; } !- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ! DPCollectionViewCell *cell; cell = (DPCollectionViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier: [DPCollectionViewCell cellIdentifier] forIndexPath:indexPath]; ! [self configureCell:cell forItemAtIndexPath:indexPath]; return cell; } !@end
Example: collection view
@implementation DPDynamicCollectionViewViewController !// ... continue form previous slide !!- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return kCellCount; } !- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ! DPCollectionViewCell *cell; cell = (DPCollectionViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier: [DPCollectionViewCell cellIdentifier] forIndexPath:indexPath]; ! [self configureCell:cell forItemAtIndexPath:indexPath]; return cell; } !@end
Example: collection view
@implementation DPDynamicCollectionViewViewController !// ... continue form previous slide !!- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return kCellCount; } !- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { ! DPCollectionViewCell *cell; cell = (DPCollectionViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier: [DPCollectionViewCell cellIdentifier] forIndexPath:indexPath]; ! [self configureCell:cell forItemAtIndexPath:indexPath]; return cell; } !@end
Conclusion
Long Story Short
• Identify the type of dynamic items you want to animate
Long Story Short
• Identify the type of dynamic items you want to animate
•Define container or reference view
Long Story Short
• Identify the type of dynamic items you want to animate
•Define container or reference view
•Create the behaviours
Long Story Short
• Identify the type of dynamic items you want to animate
•Define container or reference view
•Create the behaviours
•Add items to behaviours
Long Story Short
• Identify the type of dynamic items you want to animate
•Define container or reference view
•Create the behaviours
•Add items to behaviours
•Configure, add or remove behaviors to an animator
Tips
•Build iteratively
Tips
•Build iteratively
•Check for setup which don’t have solutions
Tips
•Build iteratively
•Check for setup which don’t have solutions
Tips
•Build iteratively
•Check for setup which don’t have solutions
Tips
•Build iteratively
•Check for setup which don’t have solutions
•Collision only for rectangle objects
Tips
•Build iteratively
•Check for setup which don’t have solutions
•Collision only for rectangle objects
Tips
•Build iteratively
•Check for setup which don’t have solutions
•Collision only for rectangle objects
•Not an physics-accurate simulation tool
Tips
•Build iteratively
•Check for setup which don’t have solutions
•Collision only for rectangle objects
•Not an physics-accurate simulation tool
•Not for games
Tips
•Build iteratively
•Check for setup which don’t have solutions
•Collision only for rectangle objects
•Not an physics-accurate simulation tool
•Not for games
• use Sprite Kit
Tips
•Build iteratively
•Check for setup which don’t have solutions
•Collision only for rectangle objects
•Not an physics-accurate simulation tool
•Not for games
• use Sprite Kit
•Focus on the user experience
Animations and Interactions
•Can combine all previous techniques
Animations and Interactions
•Can combine all previous techniques
•Core Animation
Animations and Interactions
•Can combine all previous techniques
•Core Animation
•UIView animations+(void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;
Animations and Interactions
•Can combine all previous techniques
•Core Animation
•UIView animations+(void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;
•Motion effects
Animations and Interactions
•Can combine all previous techniques
•Core Animation
•UIView animations+(void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;
•Motion effects
•Gestures
Endings
"With great power comes great responsibility."
Francois-Marie Arouet aka Voltaire
References
•Apple documentation
•WWDC 2013 sessions206 Getting Started with UIKit Dynamics221 Advanced Techniques with UIKit Dynamics217 Exploring Scroll Views in iOS 7218 Custom Transitions Using View Controllers226 Implementing Engaging UI on iOS
References
• 3rd party docsiOS 7 by tutorials Chap. 2 (by raywenderlich.com)Objc.io issue #5
•Example codeDynamicPlaygroundUIKit Dynamics Catalog (iOS Dev Library Sample Code)
Q & A
THANKS