SwiftUI - Übergang animieren
Ich habe eine Abmeldeschaltfläche auf einem Modalblatt, die den Benutzer zum Anmeldebildschirm zurückführt. Um dies zu erreichen, entlasse ich zuerst das Blatt und setze dann mit asyncAfter (Deadline :) eine Umgebungsvariable, die bewirkt, dass die Anmeldeseite angezeigt wird. Alles funktioniert einwandfrei, aber sobald das Blatt geschlossen ist, ist der Übergang von der Ansicht unter dem Blatt zur Anmeldeseite ziemlich erschütternd. Meistens, weil es keinen gibt. Die Draufsicht verschwindet einfach und zeigt die Anmeldeansicht an. Ich weiß, dass ich benutzerdefinierte Übergänge erstellen kann, aber ich kann nicht herausfinden, wo ich sie anhängen soll. Angenommen, ich möchte die Ansicht unter dem Blatt ausblenden. (Obwohl ich für jede Art von Übergang offen bin!)
Dies ist die Struktur, die den Verkehr lenkt:
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
}
}
}
}
Und dies ist die Abmeldeschaltfläche auf dem Blatt:
Button(action: {
self.presentationMode.wrappedValue.dismiss()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.tower.currentPage = .login
}
}) {
Text("Sign Out")
}
Antworten
Hier ist eine vereinfachte Demo zu Ihrem replizierten Code (und ich habe einige längere Verzögerungen vorgenommen, um den Modus sichtbar zu machen). Natürlich müssen Sie es an Ihre Bedürfnisse anpassen, indem Sie die Art des Übergangs oder der Animation usw. ändern. Getestet mit 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")
}
}
}
}