0
votes

Revised Example

Based on the thoughtful response from @pawello2222 I received in the comments below I have revised an example to demonstrate the issue I am wrestling with.

In order to demonstrate the issue I am having I am using 2 views a parent and a child. In my code code the parent view executes multiple steps but sometimes the animation subview is not visible in the first step. However when it does become visible the animation has already taken on the appearance of the end state. You can see this behavior in the following example.

Parent View

struct ContentView: View {

@State var firstTime = true
@State var breath = false

var body: some View {
    VStack {
        
        //            This subview is not displayed until after the first time
        
        if !firstTime {
            SecondView(breath: $breath)
        }
        Spacer()
        
        //            A button click simulates the steps in my App by toggling the @Binding var
        Button("Breath") {
            withAnimation {
                self.breath.toggle()
                self.firstTime = false
            }
        }
        //            This vies shows what happens when the subview is being displayed with an intial state of false for the @Binding var
        Spacer()
        SecondView(breath: $breath)
    }
}

}

Here is the subview containing the animation and using a @Binding var to control the animation appearance.

struct SecondView: View {
@Binding var breath: Bool

var body: some View {
    Image(systemName: "flame")
        .resizable()
        .rotationEffect(.degrees(breath ? 360 : 0), anchor: .center)
        .scaleEffect(breath ? 1 : 0.2)
        .opacity(breath ? 1 : 0.75)
        .animation(.easeInOut(duration: 2))
        .foregroundColor(Color.red)
}

}

When you execute this the first time thru the top subview is not being displayed and when you click the button the lower subview executes the expected animation and then toggles the firstTime var so that the top subview becomes visible. Notice that the animation is fully expanded and if I was to then have another step (click) with the same value of true for the @Binding property the view would not change at all. This is the issue I am wrestling with. I would like to keep the subview from being at the end state if the first step is one that has toggled the Bool value even if the subview was not being displayed. In other words I would like to only initialize the subview when it is actually being displayed with a value of true so that the animation will always start out small.

This is why I was hoping to have the subview initialized the Binding var to false until it actually gets invoked for the first time (or to reset its state to the shrunk version of the animation) whichever is more feasible.

1
Would you show minimal reproducible example code? Otherwise it is just a guessing, like below, and you, most probably, will not have answer like you expected.Asperi

1 Answers

1
votes

It looks like you may want to initialise _breath with the provided parameter:

struct ContentView: View {
    @Binding var breath: Bool

    init(breath: Binding<Bool>) {
        _breath = breath
    }
}

However, if you want to use a constant value (in your example false) you can do:

struct ContentView: View {
    @Binding var breath: Bool

    init(breath: Binding<Bool>) {
        _breath = .constant(false)
    }
}

But then, why do you need the breath: Binding<Bool> parameter?


EDIT

Here is an example how to control an animation of a child view using a @Binding variable:

struct ContentView: View {
    @State var breath = false

    var body: some View {
        VStack {
            Button("Breath") {
                withAnimation {
                    self.breath.toggle()
                }
            }
            SecondView(breath: $breath)
        }
    }
}
struct SecondView: View {
    @Binding var breath: Bool

    var body: some View {
        Image(systemName: "flame")
            .imageScale(.large)
            .rotationEffect(.degrees(breath ? 360 : 0), anchor: .center)
            .scaleEffect(breath ? 1 : 0.2)
            .opacity(breath ? 1 : 0.75)
            .animation(.easeInOut(duration: 2))
    }
}