Animations in SwiftUI: Implicit and Explicit Animations

SwiftUI provides powerful tools for creating engaging user experiences through animations. Whether you want to add subtle visual cues or complex transitions, understanding how to implement animations is crucial. SwiftUI offers two primary types of animations: Implicit Animations and Explicit Animations.

What are Animations in SwiftUI?

Animations in SwiftUI allow you to create dynamic and visually appealing interfaces. Animations smoothly transition views between different states or properties, making the application feel more responsive and intuitive.

Why Use Animations?

  • Improved User Experience: Animations provide visual feedback, making the interface feel more responsive.
  • Enhanced Visual Appeal: Adds dynamism and interest to static UI elements.
  • Guidance and Clarity: Helps users understand the flow and changes within the application.

Implicit Animations

Implicit animations are applied to changes in state properties. When the property changes, SwiftUI automatically animates the transition from the old value to the new value.

How to Implement Implicit Animations

Implicit animations are applied using the .animation() modifier. Here’s how to use it:

import SwiftUI

struct ImplicitAnimationView: View {
    @State private var isTapped: Bool = false

    var body: some View {
        VStack {
            Button("Tap Me") {
                isTapped.toggle()
            }

            RoundedRectangle(cornerRadius: isTapped ? 25 : 0)
                .fill(isTapped ? .orange : .blue)
                .frame(width: 200, height: 200)
                .rotationEffect(Angle(degrees: isTapped ? 360 : 0))
                .scaleEffect(isTapped ? 1.2 : 1.0)
                .animation(.default, value: isTapped) // Implicit animation
        }
    }
}

struct ImplicitAnimationView_Previews: PreviewProvider {
    static var previews: some View {
        ImplicitAnimationView()
    }
}

Explanation:

  • @State private var isTapped: Bool = false: A state variable that toggles when the button is tapped.
  • .animation(.default, value: isTapped): Applies an implicit animation. When isTapped changes, the properties with modifiers before the animation (cornerRadius, fill, rotationEffect, and scaleEffect) animate smoothly.

Customizing Implicit Animations

You can customize the animation by specifying different animation types:

  • .default: Standard system animation.
  • .linear(duration: TimeInterval): A linear animation with a specified duration.
  • .easeIn(duration: TimeInterval): Starts slow and speeds up.
  • .easeInOut(duration: TimeInterval): Starts slow, speeds up, and ends slow.
  • .easeOut(duration: TimeInterval): Starts fast and slows down.
  • .spring(response: Double, dampingFraction: Double, blendDuration: TimeInterval): Creates a spring-like animation.
import SwiftUI

struct CustomImplicitAnimationView: View {
    @State private var isTapped: Bool = false

    var body: some View {
        VStack {
            Button("Tap Me") {
                isTapped.toggle()
            }

            RoundedRectangle(cornerRadius: isTapped ? 25 : 0)
                .fill(isTapped ? .orange : .blue)
                .frame(width: 200, height: 200)
                .rotationEffect(Angle(degrees: isTapped ? 360 : 0))
                .scaleEffect(isTapped ? 1.2 : 1.0)
                .animation(.spring(response: 0.5, dampingFraction: 0.5), value: isTapped) // Custom spring animation
        }
    }
}

struct CustomImplicitAnimationView_Previews: PreviewProvider {
    static var previews: some View {
        CustomImplicitAnimationView()
    }
}

Explicit Animations

Explicit animations are triggered programmatically using the withAnimation function. This provides more control over when and how the animation occurs.

How to Implement Explicit Animations

Use the withAnimation function to encapsulate the state change you want to animate:

import SwiftUI

struct ExplicitAnimationView: View {
    @State private var isTapped: Bool = false

    var body: some View {
        VStack {
            Button("Tap Me") {
                withAnimation(.easeInOut(duration: 0.5)) {
                    isTapped.toggle()
                }
            }

            RoundedRectangle(cornerRadius: isTapped ? 25 : 0)
                .fill(isTapped ? .orange : .blue)
                .frame(width: 200, height: 200)
                .rotationEffect(Angle(degrees: isTapped ? 360 : 0))
                .scaleEffect(isTapped ? 1.2 : 1.0)
        }
    }
}

struct ExplicitAnimationView_Previews: PreviewProvider {
    static var previews: some View {
        ExplicitAnimationView()
    }
}

Explanation:

  • withAnimation(.easeInOut(duration: 0.5)) { isTapped.toggle() }: Explicitly triggers the animation when the button is tapped. Only the state changes within the withAnimation block are animated.

Chaining Animations

You can chain animations using .delay() and .repeatForever() for more complex effects.

import SwiftUI

struct ChainedAnimationView: View {
    @State private var animate: Bool = false

    var body: some View {
        Circle()
            .frame(width: 50, height: 50)
            .foregroundColor(.red)
            .scaleEffect(animate ? 1.5 : 1.0)
            .animation(
                Animation.easeInOut(duration: 1.0)
                    .repeatForever(autoreverses: true),
                value: animate
            )
            .onAppear {
                animate = true
            }
    }
}

struct ChainedAnimationView_Previews: PreviewProvider {
    static var previews: some View {
        ChainedAnimationView()
    }
}

Explanation:

  • .repeatForever(autoreverses: true): Makes the animation repeat indefinitely, reversing the direction each time.

Comparing Implicit and Explicit Animations

Feature Implicit Animations Explicit Animations
Trigger State change via .animation() modifier Programmatically via withAnimation
Control Less control; applies to all animatable properties More control; only applies to changes within withAnimation
Use Cases Simple animations tied to state changes Complex, choreographed animations

Conclusion

Understanding and utilizing both implicit and explicit animations in SwiftUI can significantly enhance your app’s user interface. Implicit animations provide a quick and easy way to animate state changes, while explicit animations offer more control for complex and choreographed effects. By mastering these techniques, you can create engaging, dynamic, and visually appealing applications that delight your users.