Skip to main content

How to override animations with transactions

About 3 minSwiftSwiftUIArticle(s)bloghackingwithswift.comcrashcourseswiftswiftuixcodeappstore

How to override animations with transactions 관련

SwiftUI by Example

Back to Home

How to override animations with transactions | SwiftUI by Example

How to override animations with transactions

Updated for Xcode 15

SwiftUI provides a withTransaction() function that allows us to override animations at runtime, for example to remove an implicit animation and replace it with something custom.

For example, this code toggles some text between small and large sizes, animating all the way because it has an implicit animation attached:

struct ContentView: View {
    @State private var isZoomed = false

    var body: some View {
        VStack {
            Button("Toggle Zoom") {
                isZoomed.toggle()
            }

            Spacer()
                .frame(height: 100)

            Text("Zoom Text")
                .font(.title)
                .scaleEffect(isZoomed ? 3 : 1)
                .animation(.easeInOut(duration: 2), value: isZoomed)
        }
    }
}

Download this as an Xcode projectopen in new window

Transactions allow us to override existing animations on a case by case basis. For example, you might decide that in one particular circumstance you want the text’s animation to happen in a fast, linear way rather than it’s existing animation.

To do that, first create a new Transaction instance using whatever animation you want, then set its disablesAnimations value to true so you override any existing animations that would apply. When you’re ready, call withTransaction() using your transaction object, then go ahead and adjust all the state you want to change – it will all be animated using your transaction.

To demonstrate this in action, here’s our same text scaling example code except using a transaction to insert a custom animation that overrides the implicit one:

struct ContentView: View {
    @State private var isZoomed = false

    var body: some View {
        VStack {
            Button("Toggle Zoom") {
                var transaction = Transaction(animation: .linear)
                transaction.disablesAnimations = true

                withTransaction(transaction) {
                    isZoomed.toggle()
                }
            }

            Spacer()
                .frame(height: 100)

            Text("Zoom Text")
                .font(.title)
                .scaleEffect(isZoomed ? 3 : 1)
                .animation(.easeInOut(duration: 2), value: isZoomed)
        }
    }
}

Download this as an Xcode projectopen in new window

For even more control you can attach a transaction() modifier to any view you want, allowing you to override any transactions that apply to the view.

For example, we could add a second zooming text view to our example, still using a transaction to trigger the zoom animation, but this time we’re going to use the transaction() modifier on the second text view so we disable any transactions on that one view – we’re overriding the override, in effect:

struct ContentView: View {
    @State private var isZoomed = false

    var body: some View {
        VStack {
            Button("Toggle Zoom") {
                var transaction = Transaction(animation: .linear)
                transaction.disablesAnimations = true

                withTransaction(transaction) {
                    isZoomed.toggle()
                }
            }

            Spacer()
                .frame(height: 100)

            Text("Zoom Text 1")
                .font(.title)
                .scaleEffect(isZoomed ? 3 : 1)

            Spacer()
                .frame(height: 100)

            Text("Zoom Text 2")
                .font(.title)
                .scaleEffect(isZoomed ? 3 : 1)
                .transaction { t in
                    t.animation = .none
                }
        }
    }
}

Download this as an Xcode projectopen in new window

Similar solutions…
How to create basic animations | SwiftUI by Example

How to create basic animations
How to create multi-step animations using phase animators | SwiftUI by Example

How to create multi-step animations using phase animators
How to apply multiple animations to a view | SwiftUI by Example

How to apply multiple animations to a view
How to reduce animations when requested | SwiftUI by Example

How to reduce animations when requested
How to synchronize animations from one view to another with matchedGeometryEffect() | SwiftUI by Example

How to synchronize animations from one view to another with matchedGeometryEffect()

이찬희 (MarkiiimarK)
Never Stop Learning.