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

如何在Swift中为自定义详情视图添加返回滑动手势?

实现SwiftUI自定义详情页的滑动返回手势

你当前的问题在于,参考的代码是针对UIKit的UINavigationController导航栈的,但你的详情页是通过ZStack叠加+@Binding变量控制显示的,并非传统导航栈结构,所以那段扩展代码对你的场景完全不适用。下面是针对你当前实现的解决方案:

核心思路

利用SwiftUI原生的DragGesture实现从屏幕左侧向右滑动的手势,滑动到一定距离(比如屏幕宽度的1/3)时触发关闭详情页的操作,同时添加跟随手势的位移动画,模拟原生滑动返回的体验。

修改后的代码实现

1. 调整商品详情页(ProductDetailView)

struct ProductDetailView: View {
    @StateObject var MarketplaceModel = MarketplaceViewModel()
    @Binding var showDetailProduct: Bool
    @Namespace var animation: Namespace.ID
    @EnvironmentObject var marketplaceData: MarketplaceViewModel
    var productData : Product
    var product_id: String
    
    // 记录滑动偏移量
    @State private var dragOffset: CGFloat = 0

    var body: some View {
        ZStack(alignment: .leading) {
            Color.white
                .ignoresSafeArea()
            
            VStack {
                // 标题栏...
                HStack {
                    Button(action: {
                        withAnimation{showDetailProduct.toggle()}
                    }) {
                        Image(systemName: "arrow.backward.circle.fill")
                    }
                    
                    Spacer()
                    
                    ForEach(MarketplaceModel.product_details_array){ items in
                        Text(items.product_name)
                            .font(.largeTitle)
                            .fontWeight(.heavy)
                            .foregroundColor(.black)
                    }
                }
                .padding()
                
                ScrollView {
                    VStack {
                        Text(productData.product_name)
                        Text(productData.product_details)
                    }
                    .padding()
                }
            }
        }
        // 添加拖拽手势
        .offset(x: dragOffset)
        .gesture(
            DragGesture(minimumDistance: 20, coordinateSpace: .global)
                .onChanged { value in
                    // 只允许从左侧向右滑动
                    if value.translation.width > 0 {
                        dragOffset = value.translation.width
                    }
                }
                .onEnded { value in
                    let threshold = UIScreen.main.bounds.width / 3
                    if value.translation.width > threshold {
                        // 滑动距离超过阈值,关闭页面
                        withAnimation(.easeOut) {
                            showDetailProduct = false
                        }
                    } else {
                        // 滑动距离不足,回弹原位
                        withAnimation(.easeOut) {
                            dragOffset = 0
                        }
                    }
                }
        )
        .onChange(of: showDetailProduct) { newValue in
            // 页面关闭时重置偏移量
            if !newValue {
                dragOffset = 0
            }
        }
    }
}

2. 主页面(ProductPage)的小调整

主页面无需大改动,仅优化详情页叠加逻辑确保动画流畅:

// 替换原ZStack内的详情页代码
if showDetailProduct, let selectedProduct = selectedProduct {
    ProductDetailView(showDetailProduct: $showDetailProduct, productData: selectedProduct, product_id: product_id)
        .transition(.move(edge: .trailing))
        .zIndex(1)
}

额外优化建议

  • 给详情页添加阴影,滑动时随偏移量调整阴影透明度,增强视觉层次感
  • 滑动时同步调整页面缩放比例,让动画更贴近原生返回体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:40:29