SwiftUI - animacja przejścia
Mam przycisk wylogowania w arkuszu modalnym, który przenosi użytkownika z powrotem do ekranu logowania. Aby to osiągnąć, najpierw zwalniam arkusz, a następnie za pomocą asyncAfter (deadline :) ustawiam zmienną środowiskową, która powoduje wyświetlenie strony logowania. Wszystko działa dobrze, ale po odrzuceniu arkusza przejście z widoku pod arkuszem do strony logowania jest dość irytujące. Głównie dlatego, że takiego nie ma. Widok z góry po prostu znika, odsłaniając widok logowania. Wiem, że mogę tworzyć niestandardowe przejścia, ale nie wiem, gdzie je dołączyć. Powiedzmy na przykład, że chcę wygasić widok pod arkuszem. (Chociaż jestem otwarty na wszelkie zmiany!)
Oto struktura kierująca ruchem:
struct ConductorView: View {
@EnvironmentObject var tower: Tower
let onboardingCompleted = UserDefaults.standard.bool(forKey: "FirstVisit")
var body: some View {
VStack {
if tower.currentPage == .onboarding {
Onboarding1View()
} else if tower.currentPage == .login {
LoginView()
} else if tower.currentPage == .idle {
LoginView()
}
}.onAppear{
if self.onboardingCompleted {
self.tower.currentPage = .login
} else {
self.tower.currentPage = .onboarding
}
}
}
}
A to jest przycisk wylogowania na arkuszu:
Button(action: {
self.presentationMode.wrappedValue.dismiss()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.tower.currentPage = .login
}
}) {
Text("Sign Out")
}
Odpowiedzi
Oto uproszczone demo twojego zreplikowanego kodu (i zrobiłem trochę dłuższe opóźnienie, aby był widoczny). Oczywiście będziesz musiał dostosować go do swoich potrzeb, zmieniając rodzaj przejścia lub animacji itp. Testowane z Xcode 12 / iOS 14
class Tower: ObservableObject {
enum PageType {
case onboarding, login, idle
}
@Published var currentPage: PageType = .onboarding
}
struct ConductorView: View {
@EnvironmentObject var tower: Tower
let onboardingCompleted = false
var body: some View {
VStack {
if tower.currentPage == .onboarding {
Onboarding1View()
} else if tower.currentPage == .login {
Text("LoginView")
.transition(.move(edge: .trailing)) // << here !!
} else if tower.currentPage == .idle {
Text("IdleView")
}
}
.animation(.default, value: tower.currentPage) // << here !!
.onAppear{
if self.onboardingCompleted {
self.tower.currentPage = .login
} else {
self.tower.currentPage = .onboarding
}
}
}
}
struct Onboarding1View: View {
@EnvironmentObject var tower: Tower
@Environment(\.presentationMode) var presentationMode
@State private var isPresented = true
var body: some View {
Text("Login")
.sheet(isPresented: $isPresented) {
Button(action: {
self.presentationMode.wrappedValue.dismiss()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.tower.currentPage = .login
}
}) {
Text("Sign Out")
}
}
}
}