an (advanced?) animation question

I am currently able to do the following in swiftUI:
1. on a button tap, update a model object property
2. update a 'separate' swiftUI view (I call it a cell view) that has an @observedObject reference to the model object
What I want to do:

while updating the cell view, I want to draw attention to it by pulsing its background colour.

so the time line would be:
1. tap the button2. update the model object

2. update the cellView with the model change

3. update the cellView background colour (eg Color(white: 0.5))

4. animate the cellView background colour back to its original value (eg Color(white: 0.9))


Here is code that performs the basic behaviour without the animation.

Any/all help with the animation greatly appreciated.


thanks,

Mike


struct ContentView: View {
    let model = Model.shared
    var body: some View {
        VStack(alignment: .center, spacing: 30.0) {
            Button(action: {
                self.model.update()
            }) {
                Text("Tap Here")
            }
            Cell(model: model)
        }
    }
}

struct Cell: View {
    @ObservedObject var model: Model
    var body: some View {
        Text(model.myVar)
            .background(Color(white: 0.9))
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

class Model: ObservableObject {
    @Published var myVar = "Before"
    static var shared: Model {
        return Model()
    }
    func update() {
        myVar = "After"
    }
}

Replies

Hi Mike,


I played around with your code a bit. I'm no animation expert; I'm just learning about them. So this feels kind of hacky, but maybe it will help until something better comes along. I changed it so I could alternate between two strings, but the idea is the same.


I didn't see how to create an animation that starts at the time of change without adding another property (`justChanged`) to represent the temporary pulse.


Rob


struct ContentView: View {
    let model = Model.shared
    var body: some View {
        VStack(alignment: .center, spacing: 30.0) {
            Button(action: {
                self.model.update()
            }) {
                Text("Tap Here")
            }
            Cell(model: model)
        }
    }
}
  
struct Cell: View {
    @ObservedObject var model: Model
    var body: some View {
        Text(model.myVar)
            .padding()
            .background(model.justChanged ? Color(white: 0.5) : Color(white: 0.9))
            
    }
}

class Model: ObservableObject {
    @Published var myVar = "Pizza"
    @Published var justChanged: Bool = false
    static var shared: Model {
        return Model()
    }
    func update() {
        if myVar == "Pizza" { myVar = "Bananas" }
        else { myVar = "Pizza" }
        withAnimation {
            justChanged = true
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5   ) {
            withAnimation {
                self.justChanged = false
            }
        }
    }
}