swiftswiftui

Why is animation not working in a List but is working in VStack


The progress bar animates in a VStack but not in the List. Any idea why?

import SwiftUI

struct NoAmimationDemo: View {
    
    @State var progress: Double = 0.0
    
    var body: some View {
        VStack {
            Button() {
                withAnimation {
                    progress += 20.0
                }
            } label: { Text("Update") }
            
            // ✅ Animating 
            ProgressView("", value: progress, total: 100.0)

            List {
                // ❌ Not animating 
                ProgressView("", value: progress, total: 100.0)
            }
        }
    }
}

Solution

  • I believe that this is a bug, and that the intended behaviour is it should work as is. After all, if you change the progress view animation to something else, like:

    Text("Rotation")
        .rotationEffect(Angle(degrees: progress))
    

    Then both Texts animate correctly.

    You can also do

    ProgressView("", value: progress, total: 100.0)
        .rotationEffect(Angle(degrees: progress))
    

    to see the progress bar rotation being animated, but the "progression" is not animated. Ironic!

    That said, for some reason, you can fix this by just adding a .transaction modifier to the non-working progress bar - you don't even have to do anything in the closure.

    ProgressView("", value: progress, total: 100.0)
        .transaction { _ in }
    

    Even something totally unrelated, like .badge, fixes it:

    ProgressView("", value: progress, total: 100.0)
        .badge(0) // the number doesn't seem to matter
    

    It seems like there is a specific set of modifiers that fixes this behaviour. My speculation is that the modifiers in this set all do some specific thing to the ProgressView in their implementation, and that's what makes the progress view "realise" that the current Transaction is animated.

    For now I would just stick a .transaction { _ in } at the end, since it doesn't do anything in particular, other than fixing this :)