SwiftUI Animation: EaseIn only then reset

208 Views Asked by At

When the screen first appears, I want three separate Text views to fade in with different delayed times. After tapping a refresh button to get new String values, I want the animation to produce the same fade-in-from-nothing effect, just like it did when the screen first appears.

Here are the properties and methods:

let colorArray = ["Red", "Orange", "Yellow", "Green", "Blue", "Purple"]
@State private var text1 = " "
@State private var text2 = " "

let cityArray = ["Dallas", "Miami", "Nashville", "Chicago", "Los Angeles", "Seattle"]
@State private var text3 = " "

@State private var isAnimating = false

func resetValues() {
    isAnimating = false
    
    text1 = " "
    text2 = " "
    text3 = " "
}

func refreshItems() {
    resetValues()
    
    text1 = colorArray.randomElement()!
    text2 = colorArray.randomElement()!
    text3 = cityArray.randomElement()!
    
    if text1 == text2 {
        text2 = colorArray.randomElement()!
    }
    
    isAnimating = true
}

And here is the body:

    NavigationStack {
        VStack(spacing: 20) {
            Text(text1)
                .opacity(isAnimating ? 1 : 0)
                .animation(.easeIn(duration: 1).delay(0.5), value: isAnimating)
            
            Text(text2)
                .opacity(isAnimating ? 1 : 0)
                .animation(.easeIn(duration: 1).delay(1.5), value: isAnimating)
            
            Text(text3)
                .opacity(isAnimating ? 1 : 0)
                .animation(.easeIn(duration: 1).delay(2.5), value: isAnimating)
        }
        .onAppear(perform: {
            refreshItems()
        })
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                Button {
                    refreshItems()
                } label: {
                    Image(systemName: "arrow.triangle.2.circlepath")
                        .font(.system(size: 25, weight: .bold))
                }
            }
        }
    }

Here is what this looks like:

enter image description here

See when the preview first starts, I get the result I want, but when I hit the refresh button, I don't get the desired animation.

SwiftUI-Lab was helpful but didn't address the challenge that I have. Any thoughts?

1

There are 1 best solutions below

1
user1046037 On

Place within an animation block

    func refreshItems() {
        withAnimation {
            resetValues()

            text1 = colorArray.randomElement()!
            text2 = colorArray.randomElement()!
            text3 = cityArray.randomElement()!
            
            if text1 == text2 {
                text2 = colorArray.randomElement()!
            }
        }
        
        isAnimating = true
    }