Weekly Swift articles, podcasts and tips by John Sundell.

Animations

Published on 12 Feb 2019

Adding animations to an app can be a great way to both delight users, and to draw their attention to certain information or actions, through motion. When deployed in the right places, animations can really make an app appear more polished and easy to use.

iOS offers a suite of different APIs when it comes to creating animations, each geared towards certain use cases, and each offering different levels of control and customization. One such API is UIView.animate, which enables us to automatically animate changes to our UI, by simply wrapping them in a closure.

For example, here we’re using that API to move a button 100 points to the right, by modifying its center position’s x component — with a duration of 0.3 seconds:

let button = UIButton()

UIView.animate(withDuration: 0.3) {
    button.center.x += 100
}

All code placed within the passed closure will be included in the animation, whenever possible. That means that we can easily animate multiple things at once, by assigning multiple properties within that same closure — like here where we’re also animating the button’s width to become 200 points:

UIView.animate(withDuration: 0.3) {
    button.center.x += 100
    button.frame.size.width = 200
}

The UIView.animate API has many different overloads, that offer us the option to pass additional parameters when performing our animation. For example, by also passing a completion closure, we’re able to react to when the animation was completed. Here we do that by changing the button’s background color to red once its animation was finished:

UIView.animate(withDuration: 0.3, animations: {
    button.center.x += 100
    button.frame.size.width = 200
}, completion: { _ in
    button.backgroundColor = .red
})

We can continue customizing our animation further by adding even more arguments to our animate call. Here we’re delaying the start of the animation by 0.5 seconds, while also applying a curve to the animation, which will make it ease in and out of the performed changes — rather than performing them linearly (which is the default):

UIView.animate(withDuration: 0.3,
               delay: 0.5,
               options: .curveEaseInOut,
               animations: {
    button.center.x += 100
    button.frame.size.width = 200
}, completion: { _ in
    button.backgroundColor = .red
})

Another animation API that’s available since iOS 10 is UIViewPropertyAnimator, which offers much of the same functionality as the above UIView.animate API, but gives us a greater degree of control over the produced animation.

A property animator can be created in a number of different ways, one of which looks very similar to our previous animation code — it accepts a duration, an animation curve and a closure containing the code that’ll generate the animation, looking like this:

let animator = UIViewPropertyAnimator(
    duration: 0.3,
    curve: .easeInOut) {
    button.center.x += 100
    button.frame.size.width = 200
}

One benefit of property animators is that it’s quite simple to modify an animation before it has started. For example, if we wanted to also move our button down by 100 points if a certain condition was met — we could call addAnimations on our animator, inside of an if statement:

if viewHasAdditionalContent {
    // Animations added this way will be performed alongside
    // the animator's original animations (a delay can optionally
    // be applied as well).
    animator.addAnimations {
        buttonB.center.y += 100
    }
}

A key difference between using a property animator compared to UIView.animate, is that the resulting animation doesn’t start immediately. Instead, we’re in control of exactly when to start it, and we do so by calling startAnimation on our animator — like this:

animator.startAnimation()

We can even pause an animation while it’s in progress — which can be really useful if the user is deciding whether to cancel an action, or if we’re building some form of interactive animation. To do that, all we have to do is to call pauseAnimation to have it freeze in its current state:

animator.pauseAnimation()

To resume the animation again, we simply make another call to startAnimation.

Both UIView.animate and UIViewPropertyAnimator can be great tools in order to build all sorts of animations that will be performed on views. While specialized views — such as UITableView and UICollectionView — offer their own, more specific animation APIs — and while frameworks like Core Animation offer more low-level access, using the APIs mentioned in this article can be a great way to get started.

Thanks for reading! 🚀