Taking control of animations with UIViewPropertyAnimator

Now that you have a good understanding of animations through the UIView object, we should take a look at the new UIViewPropertyAnimator class. This class was introduced in iOS 10, and it give you more control over timing functions and spring animations. Pausing animations or reversing them is also possible with this new class. To introduce this class and go over the possibilities available, we'll look at the animation we ended up implementing for the HelloContacts app. Each part of the animation will be implemented with UIViewPropertyAnimator. To do this, it's wise to look at how the UIViewPropertyAnimator works first.

A UIViewPropertyAnimator is a class that you instantiate. An instance of this class is responsible for the animations you're going to perform. Note that it doesn't take care of just a single animation, you can add multiple animations to your animator. Each animation you add will be added to the currently active animations. This means that you can dynamically change an animation's end value while an animation is active, and the animator will take care that the animation continues toward the new endpoint as smoothly as possible.

To configure the timing of an animator's animation, you can use the UICubicTimingParameters and UISpringTimingParameters classes. These classes take care of the easing timing functions and the more vibrant spring timings we've seen before. With this information, it's possible to refactor our UIView animation from before to a UIViewPropertyAnimator animation. Let's go over this step by step. All code in the following snippets should replace the bounce animation for contact cells.

The first thing we create is a UISpringTimingParameters object. This object contains the configuration for the springs. Note that the velocity is CGVector. This is due to improvements Apple's made for animating a view's center when using springs. For most animations, you only need to set the dx value; this is the value the animation uses by default, as follows:

let downAnimationTiming = UISpringTimingParameters( 
        dampingRatio: 0.9, 
        initialVelocity: CGVector(dx: 20, dy: 0)) 

Next, the animator object is created. This object just needs a duration and the animation timing object we created, as follows:

let downAnimator = UIViewPropertyAnimator( 
        duration: 0.2, timingParameters: downAnimationTiming) 

The next step is to add an animation to the animator. The way this works is very similar to what you've seen. The biggest difference is that animations are now added through a separate method call instead of doing everything in a single method call. Setting up your animations like this makes your code a lot more readable, as follows:

downAnimator.addAnimations { 
    cell.contactImage.transform = 
        CGAffineTransform(scaleX: 0.9, y: 0.9) 
} 

A completion handler is added in a similar way to adding the animation. The full completion handler containing the upward part of the bounce animation will be shown shortly; but before that, we need to perform one more step for the down animation, as follows:

downAnimator.addCompletion { finished in 
} 

When you used the UIView.animate method, animations started right away. If you're using an animator object, you will need to manually start the animation:

downAnimator.startAnimation() 

Combining the snippets for the previous section will allow you to use this new animator object. Running this code gives you the down animation for the bounce. Animating back up is set up in a similar fashion. Replace the addCompletion handler you added to the animator with the following code to add the animation that bounces the image back up:

downAnimator.addCompletion { finished in 
    let upAnimationTiming = UISpringTimingParameters( 
            dampingRatio: 0.3, 
            initialVelocity: CGVector(dx: 20, dy: 0)) 
     
    let upAnimator = UIViewPropertyAnimator( 
            duration: 0.2, 
            timingParameters: upAnimationTiming) 
     
    upAnimator.addAnimations { 
        cell.contactImage.transform = 
            CGAffineTransform.identity 
    } 
     
    upAnimator.addCompletion { [weak self] finished in 
        self?.performSegue( 
            withIdentifier: "contactDetailSegue", 
            sender: self) 
    } 
     
    upAnimator.startAnimation() 
} 

Adding animations in this fashion is a lot more verbose than when you're using the UIView.animate method. However, this way is a lot more readable, and because you have an animator object, you have a lot more control over your animations. An animation created with UIViewPropertyAnimator can easily be stopped, resumed, reversed, and more.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.212.199