BenJacob
BenJacob

Reputation: 987

Animating Bindings in SwiftUI

I have the following code which partially shows or hides the Test view depending on a Binding<Bool>. I can wrap the testVisible.toggle() call in a withAnimation, however, ideally I would like to ensure that visible binding is always animated, even when called without a withAnimation. How can I make sure that whenever visible binding is changed, the change is animated?

struct ContentView: View {
    @State var testVisible: Bool = true
    
    var body: some View {
        ZStack {
            Color.white
                .onTapGesture {
                    testVisible.toggle()
                }
            
            Test(visible: $testVisible)
        }
            
    }
}

struct Test: View {
    @Binding var visible: Bool
    
    var body: some View {
        Text("Test")
            .opacity(visible ? 0.5 : 0)
    }
}

Upvotes: 4

Views: 2782

Answers (3)

malhal
malhal

Reputation: 30575

You have a mistake, in Test: View it should be a let visible not a @Binding var. let is for read access and @Binding var is when you need write access which you don't. This version animates in and out correctly:

    struct ContentView3: View {
        @State var testVisible: Bool = true
        
        var body: some View {
            ZStack {
                Color.white
                    .onTapGesture {
                        withAnimation {
                            testVisible.toggle()
                        }
                        
                    }
                
                Test(visible: testVisible)
            }
            
        }
    }
    
    struct Test: View {
        let visible: Bool
        
        var body: some View {
            Text("Test")
                .opacity(visible ? 0.5 : 0)
        }
    }

Upvotes: 0

kaevinio
kaevinio

Reputation: 520

The simple .animation() modifier is deprecated in iOS 15 and macOS 12. You need to add a value, which the animation is based on:

struct Test: View {
    @Binding var visible: Bool
    
    var body: some View {
        Text("Test")
            .opacity(visible ? 0.5 : 0)
            .animation(.linear(duration: 0.5), value: visible)
    }
}

Upvotes: 4

vacawama
vacawama

Reputation: 154593

Add a .animation() modifier to the Text view:

struct Test: View {
    @Binding var visible: Bool
    
    var body: some View {
        Text("Test")
            .opacity(visible ? 0.5 : 0)
            .animation(.linear(duration: 0.5))
    }
}

Upvotes: 4

Related Questions