Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

SwiftUI: Pattern matching causes view to animate incorrectly

I’m implementing a very simple view (ChildView) that will slide up from the bottom of ParentView when a button is tapped. I’ve reproduced the issue below in a minimal example.

struct ChildView: View {
    @Binding var foo: String?

    var body: some View {
        HStack {
            if case .some = foo {
                Text("Foo")
            }

            Spacer()

            Text("Bar")
        }
        .offset(y: foo != nil ? 0 : UIScreen.main.bounds.height)
    }
}

struct ParentView: View {
    @State private var foo: String?

    var body: some View {
        ZStack {
            Button(action: {
                withAnimation {
                    foo = "Foo"
                }
            }) {
                Text("Tap me")
            }

            ChildView(foo: $foo)
        }.frame(width: 300, height: 500)
    }
}

I pass a binding into ChildView that is a simple String? here, but ultimately it will be an enum instance which I will switch on inside ChildView.

The problem is that Text("Foo") inside ChildView doesn’t slide up from the bottom, but rather fades in place. Text("Bar") slides correctly, and the only difference is that the former touches the foo binding. See GIF below:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

enter image description here

One can observe the same thing if foo was an enum and we switched on it.

What is going on?

I saw this question, but the accepted answer didn’t work for me.

>Solution :

When the binding changes, the ChildView changes two things: Show "foo" which hadn’t been there before, and change the offset of anything else to 0.
So animation will only work on what has been there before. i.e. "Bar".

But you can change the value of elements, that are already there:

struct ChildView: View {
    @Binding var foo: String?
    
    var body: some View {
        HStack {
            Text(foo ?? "")
            
            Spacer()
            
            Text("Bar")
        }
        .offset(y: foo != nil ? 0 : UIScreen.main.bounds.height)
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading