swiftswiftuiuiviewanimationtransition

SwiftUI: How do I transition gracefully when parent view changes?


I have a view that starts setup like this.

var body: some View {
    switch appState.userFlow {
    case .onboarding:
        Text("Not Yet Implemented")
    case .login:
        LandingPageView()
    case .home:
        HomeScreenView()
    }
}

In each of those userFlow's I change the appState utilizing an @EnvironmentObject Whenever the object changes its state, the view blinks away and the new one is presented. This looks abrupt and ugly as it stands.

I attempted to do something along the lines of this. Which had no effect. What is the proper way to handle a transition when used in this context?

LandingPageView().transition(.opacity)

Solution

  • The .transition needs to be applied to the container of the views that you want to switch over, so you'll need to embed your switch inside a Group, VStack, or similar.

    Also, you need to have either a .animation(.default) on the container, or change appState.userFlow inside a withAnimation {} block to actually animate the change.

    enum UserFlow {
        case onboarding
        case login
        case home
    }
    struct ContentView: View {
        @State var userFlow = UserFlow.home
        var body: some View {
            
            /// container
            Group {
                
                switch userFlow {
                case .onboarding:
                    Text("Not Yet Implemented")
                case .login:
                    Text("Login page")
                case .home:
                    Text("Home page")
                }
                
            }
            .animation(.default) /// also need Animation
            .transition(.opacity)
            
            /// for testing
            .onAppear {
                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                    userFlow = .login
                }
            }
        }
    }
    

    Result:

    Text "Home page" fades to "Login page"