Following the tutorial at https://www.swift.org/getting-started/swiftui/:
Finally, we can use SwiftUI’s
id()modifier to attach that identifier to the whole innerVStack, meaning that when the identifier changes SwiftUI should consider the wholeVStackas new. This will make it animate the oldVStackbeing removed and a newVStackbeing added, rather than just the individual views inside it. Even better, we can control how that add and remove transition happens using atransition()modifier, which has various built-in transitions we can use.So, add these two modifiers to the inner
VStack, telling SwiftUI to identify the whole group using ouridproperty, and animate its add and removal transitions with a slide:.transition(.slide) .id(id)
However this seems to do nothing - the default fade transition is still in effect when I click the "Try again" button. Is this a bug in SwiftUI or in my code?
Full code below:
//
// ContentView.swift
// WhyNotTry
//
import SwiftUI
struct ContentView: View {
var activities = ["Archery", "Baseball", "Basketball", "Bowling", "Boxing", "Cricket", "Curling", "Fencing", "Golf", "Hiking", "Lacrosse", "Rugby", "Squash"]
var colors: [Color] = [.blue, .cyan, .gray, .green, .indigo, .mint, .orange, .pink, .purple, .red]
@State private var selected = "Baseball"
@State private var id = 1
var body: some View {
VStack {
Text("Why not try…")
.font(.largeTitle.bold())
VStack {
Circle()
.fill(colors.randomElement() ?? .blue)
.padding()
.overlay(Image(systemName: "figure.\(selected.lowercased())")
.font(.system(size: 144)))
Text("\(selected)!")
.font(.title)
}
.transition(.slide)
//.animation(.default)
.id(id)
Spacer()
Button("Try again") {
withAnimation(.easeInOut(duration: 1)) {
selected = activities.randomElement() ?? "Archery"
id += 1
}
}
.buttonStyle(.borderedProminent)
}
}
}
#Preview {
ContentView()
}
Edit: FWIW i tried the solution from Transitions: View insertion not animating and .animation(.default) didn't appear to fix this.