Benjamin B.
Benjamin B.

Reputation: 793

SwiftUI, how to make the background color animate multiple times

I have a SwiftUI project that includes a Text object with a .onTapGesture working that, when triggered, should cause the button's background color to pop to another color then quickly fade back to the original color. In my code, I'm able to trigger the color pop, but it stays that way and won't fade back. I'm kind of at a loss on what to do, any help is appreciated...here is the code I'm using:

@State var buttonFlash = false


var body: some View {
    Text("Hello")
        .font(.system(size: 20))
        .frame(width: 30, height: 30)
        .foregroundColor(Color.blue)
        .background(buttonFlash ? Color.white : Color.red)
        .animation(nil)
        .background(Color.red)
        .animation((Animation.linear).delay(0.1))
        .cornerRadius(30)
        .onTapGesture {
            print("Tapped!")
            self.buttonFlash.toggle()

        }

Upvotes: 2

Views: 5701

Answers (2)

Simon
Simon

Reputation: 1870

should cause the button's background color to pop to another color then quickly fade back to the original color.

You need to declare a function for that. Here is a possible approach for it:

struct ContentView: View {
    
    @State var buttonFlash: Bool = false
    
    var body: some View {
        Text("Hello")
            .font(.system(size: 20))
            .frame(width: 100, height: 50)
            .foregroundColor(Color.blue)
            .background(buttonFlash ? Color.white : Color.red)
            .cornerRadius(30)
            .onTapGesture {
                print("Tapped!")
                self.colorChange()
            }
    }
    
    private func colorChange() {
        // first toggle makes it red
        self.buttonFlash.toggle()
        
        // wait for 1 second
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: {
            // Back to normal with ease animation
            withAnimation(.easeIn){
                self.buttonFlash.toggle()
            }
        })
    }
}

It calls the method once tapped. This then triggers the color change and reverses it after 1 second.

Produces this outcome:

enter image description here

Upvotes: 2

Frankenstein
Frankenstein

Reputation: 16361

If you're trying to flash the backgroundColor multiple number of times. Use a method and loop over until a condition is met. Here's an example:

struct ContentView: View {

    @State private var buttonFlash: Bool = false
    @State private var numberOfTimes = 6

    var body: some View {
        Text("Hello")
            .font(.system(size: 20))
            .frame(width: 300, height: 50)
            .foregroundColor(Color.blue)
            .background(buttonFlash ? Color.white : Color.red)
            .animation(nil)
            .background(Color.red)
            .animation((Animation.linear).delay(0.1))
            .cornerRadius(30)
            .onTapGesture {
                print("Tapped!")
                self.animate()
            }
    }

    private func animate() {
        self.buttonFlash.toggle()
        if numberOfTimes > 0 {
            numberOfTimes -= 1
        } else {
            numberOfTimes = 6
            return
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
            self.animate()
        })
    }
}

Upvotes: 0

Related Questions