UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

How to animate views using UIViewPropertyAnimator

Swift version: 5.6

Paul Hudson    @twostraws   

iOS 10 introduced a new closure-based animation class in the form of UIViewPropertyAnimator. Amongst other things, it lets you interactively adjust the position of an animation, making it jump to any point in time that we need – a technique commonly called scrubbing.

To try it yourself, create a new Single View App project targeting iPad, then lock it so that it supports landscape only and use Interface Builder to embed its view controller inside a navigation controller.

To demonstrate animation scrubbing we’re going to create a UISlider then fix it to the bottom of our view, spanning the full width.

Open ViewController.swift and add this code to viewDidLoad():

let slider = UISlider()
slider.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(slider)

slider.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
slider.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true

When that slider is dragged from left to right, it will count from 0 to 1 and we’re going to use that to manipulate an animation of a red box sliding across the screen.

Add this code to viewDidLoad():

let redBox = UIView(frame: CGRect(x: -64, y: 0, width: 128, height: 128))
redBox.translatesAutoresizingMaskIntoConstraints = false
redBox.backgroundColor = UIColor.red
redBox.center.y = view.center.y
view.addSubview(redBox)

That creates a 128x128 red box, centered vertically and part-way off the left edge of the screen. Even though we’re going to manipulate it elsewhere in the app, we don’t need a property for it – UIViewPropertyAnimator works using closures, so it will capture the box for us.

Next, add a property for the animator:

var animator: UIViewPropertyAnimator!

We’re going to make the animation move the box from the left to the right, while spinning around and scaling down to nothing. All that will happen over two seconds, with an ease-in-ease-out curve. Add this to the end of viewDidLoad():

animator = UIViewPropertyAnimator(duration: 2, curve: .easeInOut) { [unowned self, redBox] in
    redBox.center.x = self.view.frame.width
    redBox.transform = CGAffineTransform(rotationAngle: CGFloat.pi).scaledBy(x: 0.001, y: 0.001)
}

That doesn’t actually run the animation, which is OK for now. Instead, it creates the animation and stores it away in the animator property, ready for us to manipulate.

At this point, we have a slider on the screen and a red box too, so we just need to connect it all. When the slider is moved, its .valueChanged event will be triggered, and we can add a method to catch that. We can actually feed the slider’s value property – the number from 0.0 to 1.0 – directly into the fractionComplete property of our UIViewPropertyAnimator, which controls how much of the animation has happened, and UIKit will take care of the rest for us.

Add this method to ViewController:

@objc func sliderChanged(_ sender: UISlider) {
    animator.fractionComplete = CGFloat(sender.value)
}

To make that get called by the slider, add this to viewDidLoad():

slider.addTarget(self, action: #selector(sliderChanged), for: .valueChanged)

That’s it! We’ve created the user interface, prepared an animation, then connected the slider’s value to the animation’s progress. If you run the app now you’ll see you can drag the slider from left to right and back again to manipulate the box – you literally have exact control over its position in the animation.

If you wanted to make the animation play the traditional way – i.e., without user control – just call its startAnimation() method. You can also set animator.isReversed = true to force the animation to move backwards, ultimately returning to its starting state.

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Available from iOS 10.0

Similar solutions…

About the Swift Knowledge Base

This is part of the Swift Knowledge Base, a free, searchable collection of solutions for common iOS questions.

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 3.4/5

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.