Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI conditional view will not animate/transition

I’m trying to get my views to animate/transition using .transition() on views. I use similar code from here and put .transition() to both conditional views.

struct Base: View {
    @State private var isSignedIn = false

    var body: some View {
        Group {
            if(isSignedIn){
                Home().transition(.slide)
            }else{
                AuthSignin(isSignedIn: self.$isSignedIn).transition(.slide)
            }
        }
    }
}

struct AuthSignin: View {
    @Binding var isSignedIn: Bool

    var body: some View {
        VStack {
            Button(action: {
                self.isSignedIn = true
            }) {
                Text("Sign In")
                    .bold()
                    .frame(minWidth: CGFloat(0), maxWidth: .infinity)
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(Color.white)
                    .cornerRadius(CGFloat(10))
            }.padding()
        }
    }
}

However, whenever I click on the "Sign In" button (with or without .transition()), the app will freeze for a second and then the Home() view will suddenly appear without any animation/transition. I've also tried to wrap self.isSignedIn = true in withAnimation but it still won't work. Any ideas or is there a better way to do this?

like image 932
leftysauce Avatar asked Nov 27 '19 06:11

leftysauce


1 Answers

Place your .transition on the container of the views that will switch, not each conditional view. Here's a trivial example from some code I have done (which works).

In the main View that needs to transition conditionally:

import SwiftUI

struct AppWrapperView: View {

  @State var showFirstRun:Bool = true

  var body: some View {
    ZStack {
      if (showFirstRun) {
        FirstRunView(showFirstRun: $showFirstRun)
      } else {
        Text("Some other view")
      }
    }
    .transition(.slide)
  }
}

Then, somewhere in the view that triggers the change in condition:

import SwiftUI

struct FirstRunView: View {

  @Binding var showFirstRun:Bool

  var body: some View {

    Button(action: {
      withAnimation {
        self.showFirstRun = false
      }
    }) {
      Text("Done")
    }
  }
}
like image 191
codewithfeeling Avatar answered Oct 11 '22 17:10

codewithfeeling