Вот правильный подход, некоторые пояснения приведены ниже и в комментариях. Протестировано с Xcode 11.2 / iOS 13.2
Напоминание: не тестировать переходы в режиме предварительного просмотра - только на имитаторе или устройстве
// !! Don't name your types as API,
// State is SwiftUI type, might got unpredictable weird issues
class SolutionState:ObservableObject{
@Published var showSolution = false
}
struct TestBrokenAnimation: View {
@EnvironmentObject var state:SolutionState
var body:some View {
VStack {
if state.showSolution{
CustomToggleOne()
.background(Color.red)
.id("one")
.transition(.slide) // implicit animations confuse transition, don't use it
} else {
CustomToggleTwo()
.background(Color.yellow)
.id("two")
.transition(.slide)
}
}
}
}
public func withAnimation<Result>(_ animation: Animation? = .default,
_ body: () throws -> Result) rethrows -> Result
, как он видел withAnimation
не является состоянием, которое просто активирует анимации, определенные с помощью модификатора, оно явно применяет указанную собственную анимацию, поэтому наличие большего количества модификаторов определенно приведет к некоторым конфликтам .
Таким образом, используя только явные анимации с переходами.
struct CustomToggleOne: View{
@EnvironmentObject var state:SolutionState
var body:some View{
HStack{
Spacer()
Button(action:{
withAnimation(Animation.default.delay(2)) {
self.state.showSolution.toggle()
}
}){
Text("Next")
}.padding()
Spacer()
}
}
}
struct CustomToggleTwo: View{
@EnvironmentObject var state:SolutionState
var body:some View{
HStack{
Spacer()
Button(action:{
withAnimation() {
self.state.showSolution.toggle()
}
}){
Text("Next")
}.padding()
Spacer()
}
}
}