Everyone knows how to create simple animations, but what if you want to create awesomely fantastically beautiful animations? Marin Todorov, a team member of raywenderlich.com, shows what you can achieve if you really know your layers and animation libraries. There wonāt be any magic in this presentation - just powerful, impressive animations!
Code samples from this talk can be found on GitHub.
New in iOS 9 (0:35)
There arenāt so many new things for animations in iOS 9. UIViewAnimationOptions
is now an OptionSetType
. Before, it was just values that you could combine in a bit mask. You have all the values that you had before as elements of the set, so you can combine them together and use them in this way. In iOS 8 you had to say nil
if you didnāt want any options in your view animations. Now you just put square brackets to declare an empty set. In iOS 9, you can also combine options like Repeat
and CurveLinear
within the brackets. If you have just one option, you donāt need brackets, so thatās the weird one out. The set will actually figure out if the option is one of the elements, and then process it just fine.
// iOS 8
UIView.animateWithDuration(1.0, delay: 0.0, options: nil, animations {
v.center.y += 100.0
}, completion: nil)
// iOS 9
UIView.animateWithDuration(1.0, delay: 0.0, options: [], animations {
v.center.y += 100.0
}, completion: nil)
The other new thing is with spring animations. In iOS 9, you can actually go one level lower and use CASpringAnimation
for your layers. This class used to be in iOS, but it was a private class. Itās actually the class that has been driving your view spring animations all along. Just this year, Apple decided to give it to us all, so we can stop using open source spring animation implementations. One thing you need to know if you didnāt really use spring animations before is that you need to provide a mass
, spring stiffness
, and damping
. The animation will then solve the system for you. Once you provide these values, you can access settlingDuration
. This is a read-only property, and the animation will tell you in what time it will settle.
// iOS 8
UIView.animateWithDuration(1.0, delay: 0.0,
usingSpringWithDamping: 0.25, initialSpringVelocity: 0.12,
options: [], animations: {
v.center.x += 100.0
}, completion: nil)
// iOS 9
class CASpringAnimation : CABasicAnimation {
var mass: CGFloat
var stiffness: CGFloat
var damping: CGFloat
var initialVelocity: CGFloat
var settlingDuration: CFTimeInterval { get }
}
Introduction to Animations (4:46)
In iOS 7, we migrated our apps into a new visual style. But if an app has no graphical style to it that you can recognize, thereās no way of telling whether itās by an indie developer or Apple. You can change the tint of your app with colorful text, but to actually make a big difference, you need to add some animations.
Animations make a real difference in communicating everything about your brand and style. The good thing is that everybody knows how to do some animations. With views, itās really to just animate something as simple as moving a red square a few points to the right. If you donāt use Swift, itās about time. The problem is that I think many people would stop at moving shapes across the screen or fading them in and out. Anytime you feel like doing something more, you just go to Stack Overflow and get a very specific answer. It works, but if you want to do something else, you need to post another question to Stack Overflow.
Experiment š„ (7:20)
I think the best way to approach animations is to experiment. Core Animation, and particularly UIKit as well, provide you with so many things that you can use to create animations in your app. I think itās really powerful, and itās really fantastic. Iām going to show you three things that you can do. You can try different properties, experiment with new layers, and then think out of the box and do crazy stuff beyond animating with duration. For this talk, Iām going to be using EasyAnimation, which just adds a couple of features to UIKit.
Demo (8:23)
I have a few examples in this demo, just to show you what Easy Animation does. I have an app that has a āplusā button, which will probably add some stuff when we tap on it. Animations in user interface are usually used to provide feedback to the user, to tell the user something is going on. So, I want to just make the button bounce using Easy Animationās UIView.animateAndChainWithDuration
. Easy Animation just adds a couple methods that really fit into whatās already provided by UIKit. This method allows you to build sequences very easily, so that you can experiment really quickly.
Iāll set a 0.25 delay
and use CurveEaseOut
, which slows down towards the end to build tension. My blue square is my button, so Iāll transform it and simply scale it down a bit. Easy Animation allows me to just add a dot at the end of the first animation, and then add another one. Iāll put a spring animation next, so that the button rotates a bit and scales it up.
UIView.animateAndChainWithDuration(0.25, delay: 0.0, options: .CurveEaseOut, animations: {
self.blueSquare.transform = CGAffineTransformMakeScale(0.8, 0.8)
}, completion: nil).animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.33, initialSpringVelocity: 0.0, options: nil, animations: {
self.blueSquare.transform = CGAffineTransformConcat(
CGAffineTransformMakeScale(1.33, 1.33),
CGAffineTransformMakeRotation(CGFloat(-M_PI_2))
)
}, completion: nil)
1. Experiment With Properties (11:47)
The first thing I said to do was experiment with properties. CALayer
gives us a lot of properties to experiment with, which can all be found in its documentation. Creating animations with some of them may not be obvious, like with cornerRadius
, but they do pretty cool things.
Demo: CALayer
(12:18)
So, let me animate a cornerRadius
and set it to 50.0
in the second animation of the chain. For the first one Iāll put zero. Every time it will just run up and then go back to being a full square. The blob-like motion that results comes from combining these properties. Thereās two reasons for that. One is that I used the spring animation in here, and the other one was that I just rounded off the corners and rotated at the same time. Just like that, weāve built a really cool animation. We can also animate the border animation. I can give it a border and just remove it so that it looks like it takes a little bit of etching.
UIView.animateAndChainWithDuration(0.25, delay: 0.0, options: .CurveEaseOut, animations: {
self.blueSquare.transform = CGAffineTransformMakeScale(0.8, 0.8)
self.blueSquare.layer.cornerRadius = 0.0
self.blueSquare.layer.borderWidth = 5.0
}, completion: nil).animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.33, initialSpringVelocity: 0.0, options: nil, animations: {
self.blueSquare.transform = CGAffineTransformConcat(
CGAffineTransformMakeScale(1.33, 1.33),
CGAffineTransformMakeRotation(CGFloat(-M_PI_2))
)
self.blueSquare.layer.cornerRadius = 50.0
self.blueSquare.layer.borderWidth = 0.0
}, completion: nil)
Demo: CAShapeLayer
(14:49)
Letās look at even crazier layer properties. In CAShapeLayer
, lineDashPattern
and lineDashPhase
can let you create marching ants. When you have a selection in a photo, the selection will show up as a dashed rectangle. So, suppose in this example I have a crop tool. My selection is a CAShapeLayer
, and I can add the lineDashPattern
, which will let me specify how many pixels should be on and off in the dashed line. I can then animate the line using lineDashPhase
, which tells CoreAnmation when to start drawing the pattern.
override func viewWillAppear(animated: Bool) {
...
view.layer.addSublayer(selection)
//configure the dash pattern
selection.lineDashPattern = [5, 3]
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
...
//let the ants march!
UIView.animateWithDuration(0.5, delay: 0.0, options: .CurveLinear | .Repeat, animations: {
self.selection.lineDashPhase = 8.0
}, completion: nil)
}
2. Experiment With Layers (17:43)
My second point is to experiment with layers. You have many more layers than just CALayer
or CAShapeLayer
, and many of them exhibit at least one new property to animate. My favorite layer is CAReplicatorLayer
.
Demo: CAReplicatorLayer
(17:59)
CAReplicatorLayer
is basically a container layer, so when you put something in, it makes sure to create more copies of it for you. You just add it on the screen, add things to it, which just show up. In this example, I have one replicated layer that is just a dot. I can animate it so that it scales a bit.
//add a replicator layer
let r = CAReplicatorLayer()
r.frame = view.bounds
view.layer.addSublayer(r)
//make a simple dot layer
let dot = CALayer()
dot.bounds = CGRect(x: 0.0, y: 0.0, width: 5.0, height: 5.0)
dot.position = CGPoint(x: 18.0, y: view.center.y)
dot.backgroundColor = UIColor.greenColor().CGColor
dot.borderColor = UIColor(white: 1.0, alpha: 1.0).CGColor
dot.borderWidth = 1.0
dot.cornerRadius = 2.0
r.addSublayer(dot)
UIView.animateWithDuration(0.5, delay: 0.0, options: .CurveEaseOut | .Repeat | .Autoreverse, animations: {
dot.transform = CATransform3DMakeScale(1.4, 10, 1.0)
}, completion: nil)
When I see this dot, it reminds me of Siri and sine waves, so letās try to make it look like that using CAReplicatorLayer
. When you add to your replicator layer, you need to tell the replicator what to do with it. First Iāll say that I want thirty-five copies of my dot, with a time delay between them. Whatever I do to my original one, the replicator layer will do to all the rest. For example, I add a tenth of a second to the start time from copy to copy, so it builds up as each copy is delayed from the previous copy. Finally, the property instantTransform
allows me to tell where the position of each copy should be. So, Iāll just say to translate by twenty points to the right, which will cause each copy to be twenty points from the previous one. Then, I can animate on the replicated layer so that the position in-between each copy is being animated.
r.instanceCount = 35
r.instanceDelay = 0.1
r.instanceTransform = CATransform3DMakeTranslation(20.0, 0.0, 0.0)
UIView.animateWithDuration(1.25, delay: 0.0, options: .Repeat | .Autoreverse, animations: {
r.instanceTransform = CATransform3DMakeTranslation(10.0, 0.0, 0.0)
}, completion: nil)
Demo: TableView Animations (21:55)
A few friends and I were looking at the Skyscanner app, which shows you flight results. If you look for a given destination, you get a table of flights. When you click on one, it just pushes a new screen and shows you the same result on top, followed by the details of the flight. When you have multiple view controllers like that, you have to animate them on screen. What I did was sent one view to the left, and the other came from the right. The extra cool animation that I created was to take a snapshot of the select, create a new view that I used only for the transition, and add that to the screen. Skyscanner did exactly that.
After you select a flight, the row with that flight stays on screen, moves to the top, and then lets the view with the details slide in under it. Just take the cell from the table view, call snapshot view after the screen updates on it, and then get back a new UIView
that is a copy. What I then did was to add it to the transition container view and manipulate it to fade out, and then kill it. Code for this can be found here.
3. Experiment Withā¦Anything? (24:28)
The last example I have is to tell you to experiment with everything. By everything, I mean look through some weird blogs or go to Appleās documentation. I found this one buried really deep, so it took me a little while to put it on the actual iPhone. In this example, I have a list of posts with some photos. I created a custom view controller transition that pushes the image on screen and takes it off in a crazy manner when you tap on it.
Core Image provides you with a way to create image transitions using Core Image transition filters. Those allow you to transition one image into another one by providing a mask, so you can create custom filters of any kind by coming up with a mask. Masks can be anything black and white, and the transition will first show the black parts, followed by the grey ones, and finally the white ones. Youāll need to pull the filter all the time to take frames out of it, and then animate them on screen. You can see some of the masks I have here.
Thank you.
Receive news and updates from Realm straight to your inbox