UIKit Dynamics was unveiled in WWDC 2013, for iOS 7.
The goal was to make it easy to create animated views and transitions, based on physics.
What about Core Animation, UIView Animation, etc
We already can animate views using various techniques, such as:
-
the popular animate(withDuration:animations:), and
-
Core Animation, which we covered earlier.
So why need UIKit Dynamics?
In short, UIKit Dynamics is a better, physics-inspired framework.
A composable, reusable, declarative, real-world inspired animation, and interaction system.
UI Dynamics is like Sprite Kit, but for non-gaming apps.
(Note: Core Animation is great, but it is for pure animation. It has no “physics engine”, no collision detection and sort. So choose the framework you need.)
Architecture
- UIDynamicAnimator
- Has a reference view (think of it as a canvas)
- Provide overall context
- Keep track of all the behavioiurs
- UIDynamicBehavior
- Declarative
- Composable
- Configure the parameters then add to animator
- UIDynamicItem/View
- UIDynamicItem is a protocol, providing UIKit the information it needs to animate an item
UIView
implements it, but you can implement it too- Behaviour-View is n-n
Primitive Behaviours
You can create/compose your own UIDynamicBehavior
, but these common ones are provided out of the box:
- Gravity
Earth GravityUI Kit Gravity = 1000 point/sec^2
- Collision
- Between items or boundary
- Attachment
- Spring
- Snap
- Snap in place
- Push
Newton ForceUIKit Newton = Accelerate (100,100) to 100 point/sec^2- Continuous or instantenous
- UIDynamicItemBehavior
- Item-level properties: friction, elasticiy, density, etc
The Swift Code
This is how you create a simple physics behaviour (actually made up of 3 UIDynamicBehavior
) of an image view falling through gravity and bouncing off the container view:
// The view controller must hold on to the animator object
var animator: UIDynamicAnimator!
override func viewDidLoad() {
super.viewDidLoad()
// Create the animator
animator = UIDynamicAnimator(referenceView: view)
// Create behaviour #1 - Gravity
let gravity = UIGravityBehavior(items: [imageView])
animator.addBehavior(gravity)
// Create behaviour #2 - Collision
let collision = UICollisionBehavior(items: [imageView])
collision.translatesReferenceBoundsIntoBoundary = true
animator.addBehavior(collision)
// Create behaviour #3 - Elasticity etc
let behaviour = UIDynamicItemBehavior(items: [imageView])
behaviour.allowsRotation = false
behaviour.elasticity = 0.5
animator.addBehavior(behaviour)
}
With Autolayout
Autolayout is incompatitble with animation - using UIKit Dynamics or Core Animation.
In Core Animation, the framework works on the presentation layer, while the actual model has to be explicitly updated when the animation is completed.
This is the same for UIKit Dynamics.
Use the animator’s delegate to know when the animation is completed, and update your autolayout constraints to the final state..
// In `viewDidLoad`, set the delegate
animator.delegate = self
// UIDynamicAnimatorDelegate
func dynamicAnimatorDidPause(animator: UIDynamicAnimator) {
// Update the constraint to the final state
}
UICollectionView
UICollectionViewLayoutAttributes
also implements UIDynamicItem
.
This provides some cool animation to all the items in a collection view.
objc.io has a good tutorial on UICollectionView with dynamic animator, with the source in github.