Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI animations differ if called from within a VStack or NavigationItem

Tags:

swiftui

I've got a very simple VStack, based directly off of one of Paul Hudson's excellent SwiftUI samples. There are two lines of Text, one hidden. There's a method to toggle an @State var which controls the hidden Text.

If I call that function from within the VStack, it animates properly. If I call it from a navigationBarItems, it loses the animation. Am I missing something about how views are composed?

struct ContentView: View {
    @State var showDetails = false
    func toggleDetails() { withAnimation { self.showDetails.toggle() } }

    var body: some View {
        NavigationView() {
            VStack {
                Button(action: { self.toggleDetails() }) { Text("Tap to show details") }

                if showDetails { Text("Details go here.") }
            }
            .navigationBarTitle(Text("Nav Bar"))
            .navigationBarItems(trailing: 
               Button(action: { self.toggleDetails() }) {
                    Text("Details")
               })
        }
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

Inconsistent Animations

like image 887
Ben Gottlieb Avatar asked Dec 06 '25 08:12

Ben Gottlieb


1 Answers

Beta 5 Update

It seems beta 5 fixed this problem. Workaround no longer needed.


Workaround for beta 4 and previous versions

I think the reason it does not work, is because you are calling withAnimation from a different branch of the view tree. The "Details" button and the views that need to be animated are on different branches of the hierarchy. I am just guessing, but it seems to be supported by the workaround I posted here.

If instead of using explicit animations (i.e., withAnimation), you use implicit animations on both the VStack and the Text, it works:

enter image description here

struct ContentView: View {
    @State var showDetails = false
    func toggleDetails() { self.showDetails.toggle() }

    var body: some View {
        NavigationView() {
            VStack {
                Button(action: { self.toggleDetails() }) { Text("Tap to show details") }

                if showDetails {
                    Text("Details go here.").animation(.basic())

                }
            }
            .animation(.basic())
            .navigationBarTitle(Text("Nav Bar"))
            .navigationBarItems(trailing:
                Button(action: {
                    self.toggleDetails()

                }) { Text("Details") })
        }
    }
}
like image 89
kontiki Avatar answered Dec 09 '25 06:12

kontiki



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!