При следующем подходе вы можете изменить appMode
, используя sh (onAppear, onTapGesture и т. Д. c.). Длительность анимации, конечно, может быть установлена любой, какой вы будете sh (как и тип перехода, на самом деле, однако некоторые переходы ведут себя плохо в режиме предварительного просмотра и должны быть протестированы на симуляторе или реальном устройстве).
Демонстрация: (первый миг - просто предварительный запуск, затем два перехода для onAppear, затем для onTap)

Протестировано с Xcode 11.4 / iOS 13.4 - работает и в Предпросмотре, и в Симуляторе.
Код: Важные части помечены комментариями, встроенными.
var body: some View {
ZStack {
// !! to keep background deepest, `cause it affects removing transition
Color.blue.zIndex(-1)
// !! keep any view in explicit own `if` (don't use `else`)
if .game == self.appStore.appMode {
GameView()
.transition(AnyTransition.scale.animation(.easeInOut(duration: 1)))
}
if .options == self.appStore.appMode {
OptionsView()
.transition(AnyTransition.scale.animation(.easeInOut(duration: 1)))
}
if .menu == self.appStore.appMode {
MenuView()
.transition(AnyTransition.scale.animation(.easeInOut(duration: 1)))
}
}
}
Обновление: для .slide
(и, возможно, другие движущиеся переходы) изменение состояния должно быть заключено в явное withAnimation
, как показано ниже
withAnimation {
self.appStore.appMode = new_mode_here
}
Примечание: это один из переходов, который не поддерживается Preview - test в Simulator .
Пример перехода типа
...
if .menu == self.appStore.appMode {
Text("MenuView").frame(width: 300, height: 100).background(Color.red)
.transition(AnyTransition.move(edge: .bottom).combined(with: .opacity).animation(.easeInOut(duration: 1)))
}
}
.onTapGesture {
withAnimation {
let next = self.appStore.appMode.rawValue + 1
self.appStore.appMode = next > 2 ? .game : AppStore.AppMode(rawValue: next)!
}
}
