我有一个基于一些状态变量的视图。这些状态由API调用的完成块设置。 bookings
显示为ForEach
列表,我希望它们以slide
过渡出现。
slide
过渡效果很好。由于我添加了!isLoading
检查,因此不再显示这些动画。现在出现的所有动画都是ProgressView
的淡入/淡出。取消!isLoading
检查后,交错的幻灯片动画又回来了,但是我想保留此检查,以便我能够正确处理加载状态。
下面是一个独立的代码来重现该问题:
import SwiftUI
struct RoomView: View {
@State private var room: String?
@State private var bookings: [String]?
@State private var isLoading: Bool = false
var body: some View {
VStack(spacing: 0) {
if /* This is the problematic condition !isLoading, */ let room = self.room {
ScrollView {
LazyVStack(alignment: .leading) {
Text(room)
if let bookings = bookings {
ForEach(bookings.indices) { (index) in
let booking = bookings[index]
VStack(alignment: .leading) {
Text(booking)
Divider()
}
.transition(.slide)
// Stagger the animations when displaying the list
.animation(Animation.spring().delay(0.04 * Double(index)))
}
}
}
.padding()
}
} else {
// If we're loading
ProgressView("Loading Room")
}
}
.transition(.opacity)
.animation(.easeInOut)
.onAppear {
self.isLoading = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.room = "Demo room"
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
withAnimation {
self.bookings = ["Booking 1", "Booking 2", "Booking 3", "Booking 4", "Booking 5"]
self.isLoading = false
}
}
}
}
}
}
struct RoomView_Previews: PreviewProvider {
static var previews: some View {
RoomView()
}
}
SwiftUI动画是否存在一个已知问题,其中具有多个条件可能导致过渡不出现?如何解决此问题,以便保持ProgressView
过渡的交错动画和淡入淡出状态而无需取消!isLoading
检查?
答案 0 :(得分:0)
这是可能的解决方案-使视图独立。在Xcode 12 / iOS 14上进行了测试。
struct RoomView: View {
@State private var room: String?
@State private var bookings: [String]?
@State private var isLoading: Bool = false
var body: some View {
ZStack {
if isLoading {
// If we're loading
ProgressView("Loading Room")
}
if let room = self.room {
ScrollView {
LazyVStack(alignment: .leading) {
Text(room)
if let bookings = bookings {
ForEach(bookings.indices) { (index) in
let booking = bookings[index]
VStack(alignment: .leading) {
Text(booking)
Divider()
}
.transition(.slide)
// Stagger the animations when displaying the list
.animation(Animation.spring().delay(0.04 * Double(index)))
}
}
}
.padding()
}
}
}
.transition(.opacity)
.animation(.easeInOut)
.onAppear {
self.isLoading = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.room = "Demo room"
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
withAnimation {
self.bookings = ["Booking 1", "Booking 2", "Booking 3", "Booking 4", "Booking 5"]
self.isLoading = false
}
}
}
}
}
}