SwiftUI - Animasi transisi
Saya memiliki tombol keluar pada lembar modal yang membawa pengguna kembali ke layar masuk. Untuk mencapai ini saya pertama menutup sheet dan kemudian, menggunakan asyncAfter (deadline :) saya menetapkan variabel lingkungan yang menyebabkan halaman login muncul. Semuanya berfungsi dengan baik, tetapi setelah sheet ditutup, transisi dari tampilan di bawah sheet ke halaman login cukup mengejutkan. Sebagian besar karena tidak ada. Tampilan atas menghilang begitu saja, menampilkan tampilan login. Saya tahu saya dapat membuat transisi khusus, tetapi saya tidak tahu di mana harus memasangnya. Katakanlah, misalnya, saya ingin memudarkan tampilan di bawah lembar. (Meskipun, saya terbuka untuk segala jenis transisi!)
Ini adalah struct yang mengarahkan lalu lintas:
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
}
}
}
}
Dan ini adalah tombol keluar di lembar:
Button(action: {
self.presentationMode.wrappedValue.dismiss()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.tower.currentPage = .login
}
}) {
Text("Sign Out")
}
Jawaban
Berikut adalah demo yang disederhanakan pada kode yang direplikasi Anda (dan saya membuat penundaan lebih lama untuk membuatnya terlihat mode). Tentu saja Anda perlu menyesuaikannya dengan kebutuhan Anda dengan mengubah jenis transisi atau animasi, dll. Diuji dengan 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")
}
}
}
}