1
votes

So this started off as a single question but trying to answer the first question lead to me to the second. So the questions are:

  1. My initial question was is it possible to animate a view by going from just false to true and not false to true. Say for example in the following code

    Image(systemName: isTrue ? "heart.fill" : "heart") .animation(.easeIn, value: isTrue)

  2. The second question stemmed from the first because the parent view always sets the property to false (also the entire view re-renders due to other State properties) and while it re-renders it always animates the heart.

Is it not possible to change a property from the child view using @Binding? For some reason I cannot edit a value from the Binding (as seen below). I know @Binding does not own the view but I thought it had read / write capabilities.

Below is a gif showing what I mean and also the relevant code:

Text

import SwiftUI

struct FirstView: View {
    @State var isOn = false
    var body: some View {
        VStack {
            ZStack {
                
                RoundedRectangle(cornerRadius: 25.0)
                    .frame(height: 200)
                Image(systemName: isOn ? "heart.fill" : "heart")
                    .foregroundColor(.red)
                    .scaleEffect(isOn ? 1.5 : 1.0)
                    .offset(x: 10.0, y: 10.0)
                    .animation(.easeIn)
            }
            Toggle(isOn: $isOn) {
                Text("First View - Should change and animate")
            }
        }
        
    }
}

struct FirstView_Previews: PreviewProvider {
    static var previews: some View {
        FirstView()
    }
}

struct SecondView: View {
    @Binding var isOn: Bool
    var body: some View {
        VStack {
            FirstView()
            Toggle(isOn: $isOn, label: {
                Text(" 2nd View - Change but don't animate")
            })
        }
    }
}

struct SecondView_previews: PreviewProvider {
    static var previews: some View {
        SecondView(isOn: .constant(false))
    }
}
1
Thanks for asking this question with a clean, easy-to-copy-paste code snippet.Ryan

1 Answers

1
votes

Question 1

You need an animation that changes depending on isOn's state.

// on the view
 .animation(animation, value: isOn)

// define the variable animation
var animation: Animation? {
        isOn ? Animation.easeIn : nil
}

Question 2

You're already smart to use the value restriction version of .animation. That should restrict any changes in the hierarchy to just changes in that Binding value.