Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI custom animated transition in navigationView?

is there a way in SwiftUI to change the standard behaviour of NavigationView/NavigationLink, which is to slide from one view to the next? I'd like to have a custom animation/transition like fade in/out.

I'm trying out things for a while now and solved half of it but struggling with the second half. This code:

struct ContentView: View {
    @State var appeared: Double = 0.0

    var body: some View {
        NavigationView {
            VStack {
                Text("\(appeared)")
                NavigationLink(destination: ViewB()) {Text("go to View B")}
            }
            .opacity(appeared)
            .animation(Animation.easeInOut(duration: 3.0), value: appeared)
            .onAppear {self.appeared = 1.0}
            .onDisappear {self.appeared = 0.0}
        }
    }
}

Works correct when the view appears. It fades in by changing opacity to 1.0 within 3 seconds. All good. But when clicking the NavigationLink, to go to View B, it slides away this view and View B (which has the same logic) fades in slowly. I guess this is because onDisappear is actually triggered when the view is gone, not when it is about to move away.

Are there any chances to tell SwiftUI to not swipe or slide but do a custom animation/transition?

I'm using Xcode 11.2.1

like image 281
jboi Avatar asked Dec 10 '19 16:12

jboi


1 Answers

This is a bit late but I just ran into this issue and maybe my solution will help someone else that has this.

I needed to change the opacity, but I couldn't do that with a NavLink, so I did something like this:

struct example: View {
    @State var firstView = true
    @State var appeared: Double = 0
    var body: some View {
        VStack{
            if firstView{
                VStack{
                    Button(action: {
                        self.firstView = false
                    }){
                        Text("change view")
                    }
                }
            }
            else{
                VStack{
                    Text("Hello, World!")
                }
                .opacity(appeared)
                .animation(Animation.easeInOut(duration: 3.0), value: appeared)
                .onAppear {self.appeared = 1.0}
                .onDisappear {self.appeared = 0.0}
            }
        }

    }
}

The idea is that when the button is pressed (or whenever whatever calculations you need to do are performed), you can simulate a transition using an if-else{} structure.

Hope that helps!

like image 62
Evan Avatar answered Nov 12 '22 14:11

Evan