SwiftUI实现从C页面侧滑返回直接回到A页面(跳过B页面)的方法
SwiftUI侧滑返回从C直接到A(跳过B)的无动画异常解决方案
要实现从C页面侧滑返回直接回到A页面且无异常动画,核心思路是保留正常的页面跳转动画,同时拦截返回操作的路径修改:
- 从B到C时使用正常的
path.append(.viewC),确保进入C页面时有标准的push动画。 - 在C页面监听导航路径的变化,当系统自动将路径回退到
[.viewA, .viewB]时,直接将路径重置为[.viewA],触发从C到A的pop动画,跳过B页面。
修改后的完整代码如下:
import SwiftUI enum Route { case viewA, viewB, viewC } struct ContentView: View { @State private var path: [Route] = [] var body: some View { NavigationStack(path: $path) { Text("This is root view") Button { path.append(.viewA) } label: { Text("Go to screen A") } .navigationDestination(for: Route.self) { route in switch route { case .viewA: AView(path: $path) case .viewB: BView(path: $path) case .viewC: CView(path: $path) } } } } } struct AView: View { @Binding var path: [Route] var body: some View { VStack { Text("This is Screen A") Button("Go to Screen B") { path.append(.viewB) } } } } struct BView: View { @Binding var path: [Route] var body: some View { VStack { Text("This is Screen B") Button("Go to Screen C") { path.append(.viewC) // 保留正常push动画 } } } } struct CView: View { @Binding var path: [Route] @State private var isHandlingBack = false // 防止重复触发路径修改 var body: some View { VStack { Text("This is Screen C") } .onChange(of: path) { newPath in guard !isHandlingBack else { isHandlingBack = false return } // 拦截返回操作:当路径回到包含B的状态时,直接跳转到A if newPath == [.viewA, .viewB] { isHandlingBack = true withAnimation { path = [.viewA] } } } } } #Preview { ContentView() }
关键说明:
- 正常跳转动画:从B到C使用
append,确保系统播放标准的push过渡动画,解决了之前直接替换路径导致无动画的问题。 - 拦截返回逻辑:通过
onChange监听路径变化,当用户触发侧滑或点击返回按钮时,系统会先将路径回退到[.viewA, .viewB],此时我们立即将路径重置为[.viewA],系统会自动播放从C到A的pop动画,不会出现到B页面的中间状态。 - 防止循环触发:使用
isHandlingBack状态标记,避免路径修改后再次触发onChange导致的循环问题。
内容的提问来源于stack exchange,提问作者akhsary
相关产品推荐
相关产品推荐

