There are views in a ListView. The views have the transition modifiers on them but no transition occurs. The List is made to appear first before its chid views are rendered. Here's some code to illustrate the problem:
The StateObject:
class TripsStore: ObservableObject {
@Published private(set) var trips: [Trip] = []
@MainActor
func getTrips() async throws { ... }
}
The View
struct TripsStore: View {
@StateObject private var tripsStore: TripsStore = TripsStore()
@State private var progress: RequestStatus = .idle
@State private var availableTrips: Set<UUID?> = []
var body: some View {
NavigationStack {
Group {
if progress == .loading {
ProgressView()
} else {
List(tripsStore.trips) { trip in
if availableTrips.contains(trip.id) {
TripCard(trip: trip)
.transition(.asymmetric(insertion: .opacity, removal: .scale).animation(.easeInOut(duration: 3.5)))
}
}
.onAppear {
withAnimation {
tripsStore.trips.forEach { trip in
availableTrips.insert(trip.id)
}
}
}
}
}
.task {
progress = .loading
do {
try await tripsStore.getTrips()
} catch {
print(error)
}
progress = .idle
}
}
}
}
By using a GroupView, trip data is fetched and List is only rendered when that data is available. The appearing of each trip card is animated when the list is about to appear using the .onAppear modifier. Checking if a trip is available, should "insert" the trip's card into the already appeared ListView. During insertion, the transition ought to occur. Unfortunately, it's not happening. Does anyone know why? How can it be fixed?