Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI animation not occurring on update of Binding

I'm trying to create a "popup view" that appears when a bound value is non-nil.

enter image description here

I have a PopupCard class which is generic over Content and some Value

struct PopupCard<Content: View, Value>: View {
    @Binding private var data: Value?
    private let content: (Value) -> Content

    init(data: Binding<Value?>, @ViewBuilder content: @escaping (Value) -> Content) {
        self._data = data
        self.content = content
    }

    var body: some View {
        Group {
            if data != nil {
                HStack {
                    self.content(self.data!)
                        .padding()
                    Spacer()
                }
                .frame(width: UIScreen.main.bounds.width - 40)
                    .background(
                            Rectangle()
                                .fill(Color.yellow)
                                .shadow(color: Color.black.opacity(0.2), radius: 5, y: 0)
                    )
                    .offset(y: self.data == nil ? -100 : 0)
                    .animation(.default)
            }
        }
    }
}

I've also created the following extension on View

extension View {
    func popup<Content: View, Value>(data: Binding<Value?>, @ViewBuilder content: @escaping (Value) -> Content) -> some View {
        return ZStack {
            self
            VStack {
                Spacer()
                PopupCard(data: data, content: content)
            }
        }
    }
}

This all works fine, apart from the animation. The card appears and disappears as expected, but without the animation. This is demonstrated in the following Preview…

struct PopupCard_Previews: PreviewProvider {
    struct PreviewView: View {
        @State var name: String? = "Hello"
        var body: some View {
            TabView {
                Button("Toggle", action: {
                    self.name = self.name == nil ? "Hello" : nil

                    })
                    .popup(data: $name) { string in
                        Text(string)
                }
            }
        }
    }

    static var previews: some View {
        PreviewView()
    }
}

How do I get this to animate in / out?

like image 213
Ashley Mills Avatar asked Dec 02 '25 10:12

Ashley Mills


1 Answers

Here is fixed variant (if I correctly understood an intention). Tested with Xcode 11.4 / iOS 13.4

demo

struct PopupCard<Content: View, Value>: View {
    @Binding private var data: Value?
    private let content: (Value) -> Content

    init(data: Binding<Value?>, @ViewBuilder content: @escaping (Value) -> Content) {
        self._data = data
        self.content = content
    }

    var body: some View {
        Group {
            HStack {
                if data != nil {
                    self.content(self.data!).padding()
                } else {
                    Text("")
                }
                Spacer()
            }
            .frame(width: UIScreen.main.bounds.width - 40)
                .background(
                        Rectangle()
                            .fill(Color.yellow)
                            .shadow(color: Color.black.opacity(0.2), radius: 5, y: 0)
                )
                .compositingGroup()
                .offset(y: self.data == nil ? 100 : 0)
                .animation(.default)
        }
    }
}
like image 99
Asperi Avatar answered Dec 03 '25 23:12

Asperi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!