Professional Documents
Culture Documents
Bruce D. Nilo
These are confidential sessionsplease refrain from streaming, blogging, or taking pictures
Agenda
What we will cover
Agenda
What we will cover
Core concepts
Agenda
What we will cover
Agenda
What we will cover
Agenda
What we will cover
Core concepts Combining behaviors Using custom dynamic items Collection view and dynamics
Agenda
What we will cover
Core concepts Combining behaviors Using custom dynamic items Collection view and dynamics Using dynamics for view controller transitions
UIKit Dynamics
UIKit Dynamics
Real-world inspired animation and interaction system
UIKit Dynamics
Real-world inspired animation and interaction system Combinable, reusable, declarative
UIKit Dynamics
Real-world inspired animation and interaction system Combinable, reusable, declarative Does not replace for Core Animation, UIView animations
or motion effects
UIKit Dynamics
Real-world inspired animation and interaction system Combinable, reusable, declarative Does not replace for Core Animation, UIView animations
or motion effects Think interactions
Architecture
UIDynamicAnimator
Architecture
UIDynamicAnimator
UIDynamicBehavior
UIDynamicBehavior
UIDynamicBehavior
Architecture
UIDynamicAnimator
UIDynamicBehavior
UIDynamicBehavior
UIDynamicBehavior
UIDynamicItem
UIDynamicItem
UIDynamicItem
UIDynamicAnimator
UIDynamicAnimator
Track behaviors and animated items
UIDynamicAnimator
Track behaviors and animated items Wrap the underlying physics engine
UIDynamicAnimator
Track behaviors and animated items Wrap the underlying physics engine Run and optimize the animation
UIDynamicAnimator
Track behaviors and animated items Wrap the underlying physics engine Run and optimize the animation
!
UIDynamicAnimator
Track behaviors and animated items Wrap the underlying physics engine Run and optimize the animation
!
Three different modes: Views, collection view layouts, and raw items
Combining Behaviors
Combining Behaviors
Combining Behaviors
Physics lets you combine elements
Combining Behaviors
Physics lets you combine elements Base behavior class supports grouping and subclassing
Combining Behaviors
Physics lets you combine elements Base behavior class supports grouping and subclassing Sub-behaviors and top-level behaviors are similar for the animator
Combining Behaviors
Physics lets you combine elements Base behavior class supports grouping and subclassing Sub-behaviors and top-level behaviors are similar for the animator Compose your behaviors statically or dynamically
Initial setup
!
Initial setup
Set up a collision behavior and add the view Gesture began ! Add the view to an attachment behavior Gesture changed ! Update its anchor point to the gesture position Gesture ended ! Remove the attachment behavior ! Add gravity
!
Initial setup
Set up a collision behavior and add the view Gesture began ! Add the view to an attachment behavior Gesture changed ! Update its anchor point to the gesture position Gesture ended ! Remove the attachment behavior ! Add gravity
!
Initial setup
Set up a collision behavior and add the view Gesture began ! Add the view to an attachment behavior Gesture changed ! Update its anchor point to the gesture position Gesture ended ! Remove the attachment behavior ! Add gravity
!
Grouping Behaviors
Grouping Behaviors
Effects Combination
Bounce
Gravity + Collision
Lock Screen
Attraction Field
Multiple Push
Grouping Behaviors
Effects Combination
Bounce
Gravity + Collision
Lock Screen
Attraction Field
Multiple Push
Grouping Behaviors
Effects Combination
Bounce
Gravity + Collision
Lock Screen
Attraction Field
Multiple Push
Grouping Behaviors
Effects Combination
Bounce
Gravity + Collision
Lock Screen
Attraction Field
Multiple Push
Grouping Behaviors
Effects Combination
Bounce
Gravity + Collision
Lock Screen
Attraction Field
Multiple Push
Demo
Composing Behaviors
The behavior tree
UIDynamicAnimator
Magnet
Drag
Collision
Composing Behaviors
The behavior tree
UIDynamicAnimator
Magnet
Drag
Collision
Push Behavior
Push Behavior
Attachment Behavior
Composing Behaviors
The behavior tree
UIDynamicAnimator
Magnet
Drag
Collision
Push Behavior
Push Behavior
Attachment Behavior
Dynamic Item
Dynamic Item
Composing Behaviors
The behavior tree
UIDynamicAnimator
Magnet
Drag
Collision
Push Behavior
Push Behavior
Attachment Behavior
Dynamic Item
Dynamic Item
Composing Behaviors
The behavior tree
UIDynamicAnimator
Magnet
Drag
Collision
Push Behavior
Push Behavior
Attachment Behavior
Dynamic Item
Dynamic Item
Best Practices
Best Practices
Encapsulate and define your own API
Best Practices
Encapsulate and define your own API Integrate with your existing interactions
Best Practices
Encapsulate and define your own API Integrate with your existing interactions
!
Best Practices
Encapsulate and define your own API Integrate with your existing interactions
i.e. use the ending gesture velocity as an initial velocity If needed you can define per-step actions
!
Best Practices
Encapsulate and define your own API Integrate with your existing interactions
i.e. use the ending gesture velocity as an initial velocity If needed you can define per-step actions
!
Best Practices
Encapsulate and define your own API Integrate with your existing interactions
i.e. use the ending gesture velocity as an initial velocity If needed you can define per-step actions
!
Best Practices
Encapsulate and define your own API Integrate with your existing interactions
i.e. use the ending gesture velocity as an initial velocity If needed you can define per-step actions
!
Multiple UIDynamicItemBehavior changing distinct properties is fine Multiple UIDynamicItemBehavior changing the same property?
Last one wins ! Last one: Pre-order depth first walk of the behavior tree
!
Multiple UIDynamicItemBehavior changing distinct properties is fine Multiple UIDynamicItemBehavior changing the same property?
Last one wins ! Last one: Pre-order depth first walk of the behavior tree
!
Multiple UIDynamicItemBehavior changing distinct properties is fine Multiple UIDynamicItemBehavior changing the same property?
Multiple UIDynamicItemBehavior changing distinct properties is fine Multiple UIDynamicItemBehavior changing the same property?
!
Multiple UIDynamicItemBehavior changing distinct properties is fine Multiple UIDynamicItemBehavior changing the same property?
Last one wins ! Last one: Pre-order depth first walk of the behavior tree
!
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
? ?
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
Default Default
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
Default Default
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
Default Default
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.5 Default
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.5 Default
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.5 Default
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.5 0.2
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.3 0.2
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.3 0.2
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.3 0.2
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.3 Default
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.3 Default
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.3 Default
Behavior
Behavior
Behavior
Behavior
Dynamic Item
Elasticity Friction
0.3 Default
UIDynamicItem Protocol
UIDynamicItem Protocol
A way to integrate non-views items in behaviors
UIDynamicItem Protocol
A way to integrate non-views items in behaviors A protocol that all items animated by UIKit Dynamics must implement
UIDynamicItem Protocol
A way to integrate non-views items in behaviors A protocol that all items animated by UIKit Dynamics must implement
! Center
UIDynamicItem Protocol
A way to integrate non-views items in behaviors A protocol that all items animated by UIKit Dynamics must implement
! Center ! Bounds
UIDynamicItem Protocol
A way to integrate non-views items in behaviors A protocol that all items animated by UIKit Dynamics must implement
! Center ! Bounds ! Transform
UIDynamicItem Protocol
A way to integrate non-views items in behaviors A protocol that all items animated by UIKit Dynamics must implement
! Center ! Bounds ! Transform
UICollectionViewLayoutAttributes
UIDynamicItem Protocol
A way to integrate non-views items in behaviors A protocol that all items animated by UIKit Dynamics must implement
! Center ! Bounds ! Transform
UIDynamicItem Protocol
UIDynamicItem Protocol
Center, Bounds, and Transform are read only once by UIKit
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 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 ! Performance is critical
!
UIDynamicItem Protocol
UIDynamicItem Protocol
Will ignore any external change to Center, Transform, and Bounds
UIDynamicItem Protocol
Will ignore any external change to Center, Transform, and Bounds How to change the size of an item?
UIDynamicItem Protocol
Will ignore any external change to Center, Transform, and Bounds How to change the size of an item?
!
UIDynamicItem Protocol
Will ignore any external change to Center, Transform, and Bounds How to change the size of an item?
Remove it from its behaviors (and add it later), or ! Change a subview, or
!
UIDynamicItem Protocol
Will ignore any external change to Center, Transform, and Bounds How to change the size of an item?
Remove it from its behaviors (and add it later), or ! Change a subview, or !
!
UIDynamicItem Protocol
Will ignore any external change to Center, Transform, and Bounds How to change the size of an item?
Remove it from its behaviors (and add it later), or ! Change a subview, or ! A dynamic item should always have a valid default state
!
UIDynamicItem Protocol
Will ignore any external change to Center, Transform, and Bounds How to change the size of an item?
Remove it from its behaviors (and add it later), or ! Change a subview, or ! A dynamic item should always have a valid default state ! Non zero size
!
UIDynamicItem Protocol
Will ignore any external change to Center, Transform, and Bounds How to change the size of an item?
Remove it from its behaviors (and add it later), or ! Change a subview, or ! A dynamic item should always have a valid default state ! Non zero size ! Reasonable position
!
Example
@interface ASCIIDynamicItem : NSObject <UIDynamicItem> @property (nonatomic, readonly) CGRect bounds; @property (nonatomic, readwrite) CGPoint center; @property (nonatomic, readwrite) CGAffineTransform transform; @end
Example
@implementation ASCIIDynamicItem -(CGRect)bounds { return CGRectMake(0.0, 0.0, 100.0, 100.0); } -(CGPoint)center { return CGPointMake(50.0, 50.0); } -(CGAffineTransform)transform { return CGAffineTransformIdentity; } -(void)setCenter:(CGPoint)center { NSLog(@Center: %@, NSStringFromCGPoint(center)); } -(void)setTransform:(CGAffineTransform)transform { NSLog(@Transform: %@, NSStringFromCGAffineTransform(transform)); } @end
Add behaviors
Layout Updates
Layout Updates
Use standard collection view layout methods
Layout Updates
Use standard collection view layout methods
prepareLayout
Layout Updates
Use standard collection view layout methods
prepareLayout
!
Layout Updates
Use standard collection view layout methods
prepareLayout
!
prepareForUpdate:
Layout Updates
Use standard collection view layout methods
prepareLayout
!
prepareForUpdate:
!
Layout Updates
Use standard collection view layout methods
prepareLayout
!
prepareForUpdate:
!
layoutAttributesInRect:
Layout Updates
Use standard collection view layout methods
prepareLayout
!
Create initial setup Opportunity to add attributes to behaviors High performance itemsInRect: method on UIDynamicAnimator
prepareForUpdate:
!
layoutAttributesInRect:
!
Layout Updates
Use standard collection view layout methods
prepareLayout
!
prepareForUpdate:
!
layoutAttributesInRect:
High performance itemsInRect: method on UIDynamicAnimator ! Combine with your non-dynamics attributes
!
Layout Updates
Use standard collection view layout methods
prepareLayout
!
prepareForUpdate:
!
layoutAttributesInRect:
High performance itemsInRect: method on UIDynamicAnimator ! Combine with your non-dynamics attributes ! Off screen items might influence on screen items!
!
Demo
Interfaces
@interface DraggableLayout : UICollectionViewFlowLayout - (void)setDraggedIndexPaths:(NSArray *)selectedIndexPaths fromPoint:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; - (void)clearDraggedIndexPaths; @end @interface DragBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray*)items point:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; @end @interface RectangleAttachmentBehavior : UIDynamicBehavior - (instancetype)initWithItem:(id <UIDynamicItem>)item point:(CGPoint)p; - (void)updateAttachmentLocation:(CGPoint)p; @end
Interfaces
@interface DraggableLayout : UICollectionViewFlowLayout - (void)setDraggedIndexPaths:(NSArray *)selectedIndexPaths fromPoint:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; - (void)clearDraggedIndexPaths; @end @interface DragBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray*)items point:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; @end @interface RectangleAttachmentBehavior : UIDynamicBehavior - (instancetype)initWithItem:(id <UIDynamicItem>)item point:(CGPoint)p; - (void)updateAttachmentLocation:(CGPoint)p; @end
Interfaces
@interface DraggableLayout : UICollectionViewFlowLayout - (void)setDraggedIndexPaths:(NSArray *)selectedIndexPaths fromPoint:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; - (void)clearDraggedIndexPaths; @end @interface DragBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray*)items point:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; @end @interface RectangleAttachmentBehavior : UIDynamicBehavior - (instancetype)initWithItem:(id <UIDynamicItem>)item point:(CGPoint)p; - (void)updateAttachmentLocation:(CGPoint)p; @end
Interfaces
@interface DraggableLayout : UICollectionViewFlowLayout - (void)setDraggedIndexPaths:(NSArray *)selectedIndexPaths fromPoint:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; - (void)clearDraggedIndexPaths; @end @interface DragBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray*)items point:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; @end @interface RectangleAttachmentBehavior : UIDynamicBehavior - (instancetype)initWithItem:(id <UIDynamicItem>)item point:(CGPoint)p; - (void)updateAttachmentLocation:(CGPoint)p; @end
Interfaces
@interface DraggableLayout : UICollectionViewFlowLayout - (void)setDraggedIndexPaths:(NSArray *)selectedIndexPaths fromPoint:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; - (void)clearDraggedIndexPaths; @end @interface DragBehavior : UIDynamicBehavior - (instancetype)initWithItems:(NSArray*)items point:(CGPoint)p; - (void)updateDragLocation:(CGPoint)p; @end @interface RectangleAttachmentBehavior : UIDynamicBehavior - (instancetype)initWithItem:(id <UIDynamicItem>)item point:(CGPoint)p; - (void)updateAttachmentLocation:(CGPoint)p; @end
RectangleAttachmentBehavior
@implementation RectangleAttachmentBehavior -(instancetype)initWithItem:(id <UIDynamicItem>)item point:(CGPoint)p { if (self = [super init]) { CGPoint topLeft = CGPointMake(p.x - WIDTH / 2.0, p.y - HEIGHT / 2.0); CGPoint topRight = ... UIAttachmentBehavior* attachmentBehavior; attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:topLeft]; [attachmentBehavior setFrequency:FREQUENCY]; [attachmentBehavior setDamping:DAMPING]; [self addChildBehavior:attachmentBehavior]; attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:topRight]; ...
RectangleAttachmentBehavior
@implementation RectangleAttachmentBehavior -(instancetype)initWithItem:(id <UIDynamicItem>)item point:(CGPoint)p { if (self = [super init]) { CGPoint topLeft = CGPointMake(p.x - WIDTH / 2.0, p.y - HEIGHT / 2.0); CGPoint topRight = ... UIAttachmentBehavior* attachmentBehavior; attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:topLeft]; [attachmentBehavior setFrequency:FREQUENCY]; [attachmentBehavior setDamping:DAMPING]; [self addChildBehavior:attachmentBehavior]; attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:topRight]; ...
RectangleAttachmentBehavior
@implementation RectangleAttachmentBehavior -(instancetype)initWithItem:(id <UIDynamicItem>)item point:(CGPoint)p { if (self = [super init]) { CGPoint topLeft = CGPointMake(p.x - WIDTH / 2.0, p.y - HEIGHT / 2.0); CGPoint topRight = ... UIAttachmentBehavior* attachmentBehavior; attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:topLeft]; [attachmentBehavior setFrequency:FREQUENCY]; [attachmentBehavior setDamping:DAMPING]; [self addChildBehavior:attachmentBehavior]; attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:topRight]; ...
RectangleAttachmentBehavior
@implementation RectangleAttachmentBehavior -(instancetype)initWithItem:(id <UIDynamicItem>)item point:(CGPoint)p { if (self = [super init]) { CGPoint topLeft = CGPointMake(p.x - WIDTH / 2.0, p.y - HEIGHT / 2.0); CGPoint topRight = ... UIAttachmentBehavior* attachmentBehavior; attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:topLeft]; [attachmentBehavior setFrequency:FREQUENCY]; [attachmentBehavior setDamping:DAMPING]; [self addChildBehavior:attachmentBehavior]; attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:topRight]; ...
RectangleAttachmentBehavior
@implementation RectangleAttachmentBehavior -(void)updateAttachmentLocation:(CGPoint)p { CGPoint topLeft = CGPointMake(p.x - WIDTH / 2.0, p.y - HEIGHT / 2.0); CGPoint topRight = ... .... UIAttachmentBehavior* attachmentBehavior; attachmentBehavior = [[self childBehaviors] objectAtIndex:0]; attachmentBehavior.anchorPoint = topLeft; attachmentBehavior = [[self childBehaviors] objectAtIndex:1]; attachmentBehavior.anchorPoint = topRight; .... }
RectangleAttachmentBehavior
@implementation RectangleAttachmentBehavior -(void)updateAttachmentLocation:(CGPoint)p { CGPoint topLeft = CGPointMake(p.x - WIDTH / 2.0, p.y - HEIGHT / 2.0); CGPoint topRight = ... .... UIAttachmentBehavior* attachmentBehavior; attachmentBehavior = [[self childBehaviors] objectAtIndex:0]; attachmentBehavior.anchorPoint = topLeft; attachmentBehavior = [[self childBehaviors] objectAtIndex:1]; attachmentBehavior.anchorPoint = topRight; .... }
RectangleAttachmentBehavior
@implementation RectangleAttachmentBehavior -(void)updateAttachmentLocation:(CGPoint)p { CGPoint topLeft = CGPointMake(p.x - WIDTH / 2.0, p.y - HEIGHT / 2.0); CGPoint topRight = ... .... UIAttachmentBehavior* attachmentBehavior; attachmentBehavior = [[self childBehaviors] objectAtIndex:0]; attachmentBehavior.anchorPoint = topLeft; attachmentBehavior = [[self childBehaviors] objectAtIndex:1]; attachmentBehavior.anchorPoint = topRight; .... }
RectangleAttachmentBehavior
@implementation RectangleAttachmentBehavior -(void)updateAttachmentLocation:(CGPoint)p { CGPoint topLeft = CGPointMake(p.x - WIDTH / 2.0, p.y - HEIGHT / 2.0); CGPoint topRight = ... .... UIAttachmentBehavior* attachmentBehavior; attachmentBehavior = [[self childBehaviors] objectAtIndex:0]; attachmentBehavior.anchorPoint = topLeft; attachmentBehavior = [[self childBehaviors] objectAtIndex:1]; attachmentBehavior.anchorPoint = topRight; .... }
DragBehavior
@implementation DragBehavior -(instancetype)initWithItems:(NSArray*)items point:(CGPoint)p { if (self = [super init]) { for (id <UIDynamicItem> item in items) { RectangleAttachmentBehavior* rectangleAttachment = [[RectangleAttachmentBehavior alloc] initWithItem:item point:p]; [self addChildBehavior:rectangleAttachment]; } } return self; } - (void)updateDragLocation:(CGPoint)p { for (RectangleAttachmentBehavior* behavior in [self childBehaviors]) { [behavior updateAttachmentLocation:p]; } }
DragBehavior
@implementation DragBehavior -(instancetype)initWithItems:(NSArray*)items point:(CGPoint)p { if (self = [super init]) { for (id <UIDynamicItem> item in items) { RectangleAttachmentBehavior* rectangleAttachment = [[RectangleAttachmentBehavior alloc] initWithItem:item point:p]; [self addChildBehavior:rectangleAttachment]; } } return self; } - (void)updateDragLocation:(CGPoint)p { for (RectangleAttachmentBehavior* behavior in [self childBehaviors]) { [behavior updateAttachmentLocation:p]; } }
DragBehavior
@implementation DragBehavior -(instancetype)initWithItems:(NSArray*)items point:(CGPoint)p { if (self = [super init]) { for (id <UIDynamicItem> item in items) { RectangleAttachmentBehavior* rectangleAttachment = [[RectangleAttachmentBehavior alloc] initWithItem:item point:p]; [self addChildBehavior:rectangleAttachment]; } } return self; } - (void)updateDragLocation:(CGPoint)p { for (RectangleAttachmentBehavior* behavior in [self childBehaviors]) { [behavior updateAttachmentLocation:p]; } }
DraggableLayout
Interaction
- (void)startDraggingIndexPaths:(NSArray *)selectedIndexPaths fromPoint:(CGPoint)p { _indexPathsForDraggedElements = selectedIndexPaths; _animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self];
NSMutableArray* draggableAttributes = [NSMutableArray array]; for (NSIndexPath* path in _indexPathsForDraggedElements) { UICollectionViewLayoutAttributes* attributes = [super layoutAttributesForItemAtIndexPath:path]; attributes.zIndex = 1; [draggableAttributes addObject:attributes]; } _dragBehavior = [[DragBehavior alloc] initWithItems:draggableAttributes point:p]; [_animator addBehavior:_dragBehavior]; }
DraggableLayout
Interaction
- (void)startDraggingIndexPaths:(NSArray *)selectedIndexPaths fromPoint:(CGPoint)p { _indexPathsForDraggedElements = selectedIndexPaths; _animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self];
NSMutableArray* draggableAttributes = [NSMutableArray array]; for (NSIndexPath* path in _indexPathsForDraggedElements) { UICollectionViewLayoutAttributes* attributes = [super layoutAttributesForItemAtIndexPath:path]; attributes.zIndex = 1; [draggableAttributes addObject:attributes]; } _dragBehavior = [[DragBehavior alloc] initWithItems:draggableAttributes point:p]; [_animator addBehavior:_dragBehavior]; }
DraggableLayout
Interaction
- (void)startDraggingIndexPaths:(NSArray *)selectedIndexPaths fromPoint:(CGPoint)p { _indexPathsForDraggedElements = selectedIndexPaths; _animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self];
NSMutableArray* draggableAttributes = [NSMutableArray array]; for (NSIndexPath* path in _indexPathsForDraggedElements) { UICollectionViewLayoutAttributes* attributes = [super layoutAttributesForItemAtIndexPath:path]; attributes.zIndex = 1; [draggableAttributes addObject:attributes]; } _dragBehavior = [[DragBehavior alloc] initWithItems:draggableAttributes point:p]; [_animator addBehavior:_dragBehavior]; }
DraggableLayout
Interaction
- (void)startDraggingIndexPaths:(NSArray *)selectedIndexPaths fromPoint:(CGPoint)p { _indexPathsForDraggedElements = selectedIndexPaths; _animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self];
NSMutableArray* draggableAttributes = [NSMutableArray array]; for (NSIndexPath* path in _indexPathsForDraggedElements) { UICollectionViewLayoutAttributes* attributes = [super layoutAttributesForItemAtIndexPath:path]; attributes.zIndex = 1; [draggableAttributes addObject:attributes]; } _dragBehavior = [[DragBehavior alloc] initWithItems:draggableAttributes point:p]; [_animator addBehavior:_dragBehavior]; }
DraggableLayout
Interaction
- (void)updateDragLocation:(CGPoint)p { [_dragBehavior updateDragLocation:p]; } - (void)clearDraggedIndexPaths { _animator = nil; _indexPathsForDraggedElements = nil; }
DraggableLayout
Interaction
- (void)updateDragLocation:(CGPoint)p { [_dragBehavior updateDragLocation:p]; } - (void)clearDraggedIndexPaths { _animator = nil; _indexPathsForDraggedElements = nil; }
DraggableLayout
Interaction
- (void)updateDragLocation:(CGPoint)p { [_dragBehavior updateDragLocation:p]; } - (void)clearDraggedIndexPaths { _animator = nil; _indexPathsForDraggedElements = nil; }
DraggableLayout
Layout part
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { NSArray* existingAttributes = [super layoutAttributesForElementsInRect:rect]; NSMutableArray *allAttributes = [NSMutableArray array]; for (UICollectionViewLayoutAttributes* attributes in existingAttributes) { if (![_indexPathsForDraggedElements containsObject:attributes.indexPath]) { [allAttributes addObject:attributes]; } } [allAttributes addObjectsFromArray:[_animator itemsInRect:rect]]; return allAttributes; }
DraggableLayout
Layout part
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { NSArray* existingAttributes = [super layoutAttributesForElementsInRect:rect]; NSMutableArray *allAttributes = [NSMutableArray array]; for (UICollectionViewLayoutAttributes* attributes in existingAttributes) { if (![_indexPathsForDraggedElements containsObject:attributes.indexPath]) { [allAttributes addObject:attributes]; } } [allAttributes addObjectsFromArray:[_animator itemsInRect:rect]]; return allAttributes; }
DraggableLayout
Layout part
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { NSArray* existingAttributes = [super layoutAttributesForElementsInRect:rect]; NSMutableArray *allAttributes = [NSMutableArray array]; for (UICollectionViewLayoutAttributes* attributes in existingAttributes) { if (![_indexPathsForDraggedElements containsObject:attributes.indexPath]) { [allAttributes addObject:attributes]; } } [allAttributes addObjectsFromArray:[_animator itemsInRect:rect]]; return allAttributes; }
DraggableLayout
Layout part
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect { NSArray* existingAttributes = [super layoutAttributesForElementsInRect:rect]; NSMutableArray *allAttributes = [NSMutableArray array]; for (UICollectionViewLayoutAttributes* attributes in existingAttributes) { if (![_indexPathsForDraggedElements containsObject:attributes.indexPath]) { [allAttributes addObject:attributes]; } } [allAttributes addObjectsFromArray:[_animator itemsInRect:rect]]; return allAttributes; }
<UIViewControllerAnimatedTransitioning> <UIViewControllerInteractiveTransitioning>
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)
!
<UIViewControllerAnimatedTransitioning> <UIViewControllerInteractiveTransitioning>
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)
!
<UIViewControllerAnimatedTransitioning> <UIViewControllerInteractiveTransitioning>
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)
!
<UIViewControllerAnimatedTransitioning> <UIViewControllerInteractiveTransitioning>
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)
!
The system will call these objects with a system created object
!
<UIViewControllerContextTransitioning>
!
<UIViewControllerAnimatedTransitioning> <UIViewControllerInteractiveTransitioning>
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)
!
The system will call these objects with a system created object
!
<UIViewControllerContextTransitioning>
!
Transition Canceling No Transition Start Interactive Transition Update Interactive Transition Interaction Transition End Transition Complete No Transition
Transition Finishing
Transition Canceling No Transition Start Interactive Transition Update Interactive Transition Interaction Transition End Transition Complete No Transition
Transition Finishing
Transition Canceling No Transition Start Interactive Transition Update Interactive Transition Interaction Transition End Transition Complete No Transition
Transition Finishing
Transition Canceling No Transition Start Interactive Transition Update Interactive Transition Interaction Transition End Transition Complete No Transition
Transition Finishing
A custom non-interactive present or dismiss transition Implemented as a compound UIDynamicBehavior that conforms to
<UIViewControllerAnimatedTransitioning>
A custom non-interactive present or dismiss transition Implemented as a compound UIDynamicBehavior that conforms to
<UIViewControllerAnimatedTransitioning>
Demonstrates
A custom non-interactive present or dismiss transition Implemented as a compound UIDynamicBehavior that conforms to
<UIViewControllerAnimatedTransitioning>
! UIDynamicBehaviors
Demonstrates
action block property
A custom non-interactive present or dismiss transition Implemented as a compound UIDynamicBehavior that conforms to
<UIViewControllerAnimatedTransitioning>
! UIDynamicBehaviors ! UICollisionBehavior
Demonstrates
action block property
and UICollisionBehaviorDelegate
A custom non-interactive present or dismiss transition Implemented as a compound UIDynamicBehavior that conforms to
<UIViewControllerAnimatedTransitioning>
! UIDynamicBehaviors ! UICollisionBehavior !-
Demonstrates
action block property
and UICollisionBehaviorDelegate
A custom non-interactive present or dismiss transition Implemented as a compound UIDynamicBehavior that conforms to
<UIViewControllerAnimatedTransitioning>
! UIDynamicBehaviors ! UICollisionBehavior !!
Demonstrates
action block property
and UICollisionBehaviorDelegate
Demo
Drop in and out dialog
Wh go ere the ev re er y Go yo ou od ua to re Kn ow ?
Wh go ere the ev re er y Go yo ou od ua to re Kn ow
Wh go ere the ev re er y Go yo ou od ua to re Kn ow
Wh go ere the ev re er y Go yo ou od ua to re Kn ow
u o y r re e v a e u e er re yo h W the w o n o K g o t d o o G
Demonstrates
The interactive portion of the transition does not use UIKit Dynamics ! Use of UIDynamicBehaviors action block property to drive an interactive transition ! Use of dynamicAnimatorDidPause: to complete the transition
!
Demo
Drop shade transition
UIKit Dynamics and Custom Transitions can be used together! Subclass UIDynamicBehavior to create composite behaviors
UIKit Dynamics and Custom Transitions can be used together! Subclass UIDynamicBehavior to create composite behaviors Transitions can be comprised of multiple dynamic steps:
The UIDynamicAnimator delegate ! The UICollisionBehavior delegate ! UIDynamicBehavior actions
!
transitioning protocols How long does it take? ! You can enforce a duration by using the UIDynamicAnimators elapsedTime
transitioning protocols How long does it take? ! You can enforce a duration by using the UIDynamicAnimators elapsedTime UIDynamicBehavior actions can call updateInteractiveTransition
Wrap Up
Wrap Up
Focus on your intent
What needs animating ! Constraints (duration, interactivity, etc.)
!
Wrap Up
Focus on your intent
What needs animating ! Constraints (duration, interactivity, etc.) Other options may be more suitable
!
Wrap Up
Focus on your intent
What needs animating ! Constraints (duration, interactivity, etc.) Other options may be more suitable
!
Related Sessions
Building User Interfaces for iOS 7 Getting Started with UIKit Dynamics Introduction to Sprite Kit Exploring Scroll Views on iOS 7 Best Practices for Great iOS UI Design
Presidio Tuesday 10:15AM Presidio Tuesday 4:30PM Presidio Wednesday 11:30AM Presidio Thursday 10:15AM Presidio Friday 10:15AM