Multiple Animations in SwiftUI

DevTechie Inc
Jun 24, 2022

Animating multiple properties in SwiftUI is as easy as performing a single property animation.

There are two ways of adding animation to the views, so we will look at them one at a time as there is one slight (yet important) difference between the two.

We will start with a simple text view with “DevTechie” text. This view will have background, rotationEffect, and scaleEffect modifiers. All the modifiers will toggle between two values depending upon the value of the animate state variable. We will also toggle the background shape to be a circle or roundedRectangle with a change in the animate property.

Animating using withAnimation block.
struct MultipleAnimations: View {
    @State private var animate = false
    var body: some View {
        Text("DevTechie")
            .font(.largeTitle)
            .frame(width: 200, height: 200)
            .background(animate ? .pink : .orange, in: RoundedRectangle(cornerRadius: animate ? 200 : 20))
            .rotationEffect(.degrees(animate ? 360 : 0))
            .scaleEffect(animate ? 0.5 : 1)
            .onTapGesture { 
                withAnimation { 
                    animate.toggle()
                }
            }
    }
}
When we use withAnimation block and change values inside the block, anything observing that state property will change with animation, so order of modifier doesn’t matter.

Let’s move onTapGesture right after the font modifier.

struct MultipleAnimations: View {
    @State private var animate = false
    var body: some View {
        Text("DevTechie")
            .font(.largeTitle)
            .onTapGesture { 
                withAnimation { 
                    animate.toggle()
                }
            }
            .frame(width: 200, height: 200)
            .background(animate ? .pink : .orange, in: RoundedRectangle(cornerRadius: animate ? 200 : 20))
            .rotationEffect(.degrees(animate ? 360 : 0))
            .scaleEffect(animate ? 0.5 : 1)
            
    }
}
Our animation still works the way it was working before.

Animating with .animation(animation:, value:)
struct MultipleAnimations: View {
    @State private var animate = false
    var body: some View {
        Text("DevTechie")
            .font(.largeTitle)
            .frame(width: 200, height: 200)
            .background(animate ? .pink : .orange, in: RoundedRectangle(cornerRadius: animate ? 200 : 20))
            .rotationEffect(.degrees(animate ? 360 : 0))
            .scaleEffect(animate ? 0.5 : 1)
            .animation(.easeInOut, value: animate)
            .onTapGesture {
                animate.toggle()
            }
    }
}
Notice that we have added an animation modifier that is applied right before onTapGesture. So the reason is that we want everything which comes before the animation modifier to animate.

Let’s say that we don’t want to animate scaleEffect. In that case, we will move the animation modifier before the scaleEffect modifier, as shown below:

struct MultipleAnimations: View {
    @State private var animate = false
    var body: some View {
        Text("DevTechie")
            .font(.largeTitle)
            .frame(width: 200, height: 200)
            .background(animate ? .pink : .orange, in: RoundedRectangle(cornerRadius: animate ? 200 : 20))
            .rotationEffect(.degrees(animate ? 360 : 0))
            .animation(.easeInOut, value: animate)
            .scaleEffect(animate ? 0.5 : 1)
            .onTapGesture {
                animate.toggle()
            }
    }
}
Notice the change in animation. This is why, its important to use proper order when using animation modifier and if you want to animate everything, just use withAnimation block.



With that we have reached the end of this article. Thank you once again for reading. Subscribe to our weekly newsletter at https://www.devtechie.com