100 Days of SwiftUI Day 32

100 Days of SwiftUI – Day 32

It’s day 32 of the 100 Days of SwiftUI! Yesterday, we finished our Word Scramble project and completed a few challenges. Today, we’re diving into project number 6, which will be another technique project. We won’t be making an app, but we’ll be learning about important SwiftUI features. The focus will be on adding animations. Let’s dive in!

Introduction to animations in SwiftUI

SwiftUI features a range of animations that can be implemented into our apps. They serve a few purposes. One of them is being aesthetically pleasing, making our apps more appealing to the eye. That’s quite important in today’s day and age.

However, animations are also used to show the user the flow of information. If one View slides in over another, it’s clear to our user what has happened. If it was just to disappear, it would look a bit jarring and might leave the user wondering if that was supposed to happen.

Implicit animations

The simplest type of animation in SwiftUI is an implicit animation. In essence, we let our views know ahead of time what to do if they’re being animated. Implicit animations always need to watch a particular value, similarly to an alert. This ensures they are only triggered when required.

In the example below, we create a Button that gets bigger every time it’s tapped. To control this behaviour, we need an @State property.

@State private var animationAmount = 1.0

Button("Tap Me") {
    animationAmount += 1
}
.padding(50)
.background(.red)
.foregroundColor(.white)
.clipShape(Circle())
.scaleEffect(animationAmount)
.animation(.default, value: animationAmount)
.blur(radius: (animationAmount - 1) * 3)

Customizing animations

When we attach the animation() modifier to a view, SwiftUI will automatically animate any changes that happen to that view using whatever is the default system animation, whenever the value we’re watching changes. In practice, that is an “ease in, ease out” animation, which means iOS will start the animation slow, make it pick up speed, then slow down as it approaches its end. We can control the type of animation used by passing in different values to the modifier.

Paul Hudson, Hacking With Swift (@twostraws)
Button("Tap me") {
                // animationAmount+=1
            }
            .padding(50)
            .background(.red)
            .foregroundColor(.white)
            .clipShape(Circle())
            .overlay(
                Circle()
                    .stroke(.red)
                    .scaleEffect(animationAmount)
                    .opacity(2 - animationAmount)
                    .animation(
                        .easeInOut(duration: 2)
                        .repeatForever(autoreverses: false),
                        value: animationAmount
                    )

Animating bindings

The animation() modifier can be applied to any SwiftUI binding, which causes the value to animate between its current and new value. This even works if the data in question isn’t really something that sounds like it can be animated, such as a Boolean – you can mentally imagine animating from 1.0 to 2.0 because we could do 1.05, 1.1, 1.15, and so on, but going from “false” to “true” sounds like there’s no room for in between values.

Paul Hudson, Hacking With Swift (@twostraws)
struct ContentView: View {
    @State private var animationAmount = 1.0

    var body: some View {
        VStack {
            Stepper("Scale amount", value: $animationAmount.animation(), in: 1...10) // Applies the animation any time the value changes

            Spacer()

            Button("Tap Me") {
                animationAmount += 1
            }
            .padding(40)
            .background(.red)
            .foregroundColor(.white)
            .clipShape(Circle())
            .scaleEffect(animationAmount)
        }
    }
}

Explicit animations

You’ve seen how SwiftUI lets us create implicit animations by attaching the animation() modifier to a view, and how it also lets us create animated binding changes by adding the animation() modifier to a binding, but there’s a third useful way we can create animations: explicitly asking SwiftUI to animate changes occurring as the result of a state change.

Paul Hudson, Hacking With Swift (@twostraws)
 Button("Tap me") {
                withAnimation(.interpolatingSpring(stiffness: 5, damping: 1)) {
                    rotationAmount += 360
                }
            }
            .padding(50)
            .background(.red)
            .foregroundColor(.white)
            .clipShape(Circle())
            .rotation3DEffect(.degrees(rotationAmount), axis: (x: 0, y: 1, z: 0))

And that’s it for day 32! It’s quite easy to add very nice looking animations to our apps and this has already given me a few ideas on how to expand on our past projects to see if I can implement them on my own as well. Tomorrow, we’ll dive even further into animations with more advanced features that SwiftUI provides us with. We keep marching on!

Darryl

Hi! My name is Darryl and this is my personal blog where I write about my journey as I learn programming! You'll also find articles about other things that interest me including games, tech and anime.

Post navigation

Leave a Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

100 Days of SwiftUI – Day 25 – Rock, Paper, Scissors

100 Days of SwiftUI – Day 7 – Functions

100 Days of SwiftUI – Day 33

100 Days of SwiftUI – Day 57