You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI:ViewDrag预览拖拽正常,跳转进入后拖拽失效求助

解决NavigationStack跳转后自定义拖拽手势失效问题

问题原因

  • 嵌套NavigationStack冲突:ContentView已使用NavigationStack,ViewDrag内部再次嵌套会导致系统侧滑返回手势与自定义拖拽手势竞争,使自定义手势无法触发。
  • 页面判断逻辑冗余:currentPage最大仅为2(对应View3),但原代码中判断currentPage < 4,逻辑错误且多余。
  • 无用冗余代码:子View(View1/2/3)中声明的@GestureState private var translation: CGFloat = 0完全未使用,属于无效代码。
  • 手势捕获范围不足:默认情况下ViewDrag内容仅自适应文本大小,拖拽手势只能在文本区域触发,易被误认为失效。

修复步骤

  1. 移除嵌套的NavigationStack:ViewDrag无需单独导航栈,直接复用ContentView的导航栈即可。
  2. 修正页面切换逻辑:将currentPage < 4改为currentPage < 2(最大页面索引为2),同时移除多余的currentPage != 4判断。
  3. 删除子View冗余GestureState:去掉View1/2/3里未使用的@GestureState声明。
  4. 设置全屏容器:给ViewDrag内容添加.frame(maxWidth: .infinity, maxHeight: .infinity),确保拖拽手势能捕获整个屏幕操作。

修改后的完整代码

struct ContentView: View {
    @State var Jump = false
    var body: some View {
        NavigationStack {
            VStack {
                Button(action: {
                    Jump = true
                }, label: {
                    Text("JUMP")
                })
            }
            .navigationDestination(isPresented: $Jump, destination: {
                ViewDrag()
            })
        }
    }
}

struct ViewDrag: View {
    @State private var currentPage = 0
    @GestureState private var translation: CGFloat = 0
    
    var body: some View {
        Group {
            switch currentPage {
            case 0:
                View1(nextPage: $currentPage)
                    .transition(.customTransition)
            case 1:
                View2(nextPage: $currentPage)
                    .transition(.customTransition)
            case 2:
                View3(nextPage: $currentPage)
                    .transition(.customTransition)
            default:
                View1(nextPage: $currentPage)
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .gesture(
            DragGesture()
                .updating($translation, body: { value, state, _ in
                    state = value.translation.width
                })
                .onEnded({ value in
                    if value.translation.width < 0 && currentPage < 2 {
                        withAnimation {
                            currentPage += 1
                        }
                    } else if value.translation.width > 0 && currentPage > 0 {
                        withAnimation {
                            currentPage -= 1
                        }
                    }
                })
        )
    }
}

extension AnyTransition {
    static var customTransition: AnyTransition {
        let transition = AnyTransition.move(edge: .leading)
            .combined(with: .opacity)
        
        return .asymmetric(insertion: transition, removal: transition)
    }
}

struct View1: View {
    @Binding var nextPage: Int
    var body: some View {
        Text("I am View1")
    }
}

struct View2: View {
    @Binding var nextPage: Int
    var body: some View {
        Text("I am View2")
    }
}

struct View3: View {
    @Binding var nextPage: Int
    var body: some View {
        Text("I am View3")
    }
}

额外说明

  • 使用switch替代多个if-else让页面切换逻辑更清晰。
  • 全屏frame确保拖拽手势在屏幕任意位置都能触发,避免仅文本区域生效的问题。

内容的提问来源于stack exchange,提问作者zzhzzh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:07:07