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

SwiftUI中拖拽手势导致列表侧滑操作难以触发的解决方法

问题描述

我有一个视图,其中每个列表项都带有leading/trailing侧滑操作。给视图添加Drag手势识别器后,列表项的侧滑操作变得极难触发。我想保留屏幕左右边缘(灰色区域)的自定义拖拽手势来导航到其他视图,同时让列表项的侧滑操作正常工作,该怎么做?

原始代码

import SwiftUI

struct swipeTest: View {
    @State var offset = 0.0
    var body: some View {
        VStack {
            List {
                ForEach(0..<60, id: \.self) { _ in
                    RoundedRectangle(cornerRadius: 10)
                        .frame(height: 50).foregroundStyle(.blue).padding(15)
                        .swipeActions(edge: .trailing) {
                            Button(action: {
                                
                            }, label: {
                                Image(systemName: "bell")
                            }).tint(.orange)
                        }
                        .swipeActions(edge: .leading) {
                            Button(action: {
                              
                            }, label: {
                                Image(systemName: "pin")
                            }).tint(.green)
                        }
                }
            }.listStyle(.plain)
        }
        .offset(x: offset)
        .overlay(alignment: .leading, content: {
            // Only need swipe on very left edge
            Color.gray.opacity(0.3).frame(width: 15)
        })
        .overlay(alignment: .trailing, content: {
            // Only need swipe on very right edge
            Color.gray.opacity(0.3).frame(width: 15)
        })
        .simultaneousGesture (
            DragGesture()
                .onChanged({ value in
                    let width = widthScreen()
                    
                    if value.startLocation.x < 15.0 || value.startLocation.x > (width - 15.0) {
                        offset = value.translation.width
                    }
                })
                .onEnded({ value in
                    offset = 0.0
                })
        )
    }
}

func widthScreen() -> CGFloat {
    let scenes = UIApplication.shared.connectedScenes
    let windowScene = scenes.first as? UIWindowScene
    let window = windowScene?.windows.first
    return window?.screen.bounds.width ?? 0
}


#Preview {
    swipeTest()
}

解决方案

核心思路

全局的simultaneousGesture会和列表项的侧滑手势抢占响应权,导致列表侧滑难以触发。我们需要将边缘拖拽手势仅绑定到灰色边缘区域,而非全局视图,从根源避免手势冲突。

修改后代码

import SwiftUI

struct SwipeTest: View {
    @State var offset = 0.0
    
    var body: some View {
        GeometryReader { geo in
            let screenWidth = geo.size.width
            
            ZStack(alignment: .leading) {
                // 列表视图
                List {
                    ForEach(0..<60, id: \.self) { _ in
                        RoundedRectangle(cornerRadius: 10)
                            .frame(height: 50)
                            .foregroundStyle(.blue)
                            .padding(15)
                            .swipeActions(edge: .trailing) {
                                Button(action: {}) {
                                    Image(systemName: "bell")
                                }
                                .tint(.orange)
                            }
                            .swipeActions(edge: .leading) {
                                Button(action: {}) {
                                    Image(systemName: "pin")
                                }
                                .tint(.green)
                            }
                    }
                }
                .listStyle(.plain)
                .offset(x: offset)
                
                // 左侧边缘拖拽区域(单独绑定手势)
                Color.gray.opacity(0.3)
                    .frame(width: 15)
                    .gesture(
                        DragGesture()
                            .onChanged { value in
                                offset = value.translation.width
                            }
                            .onEnded { _ in
                                offset = 0.0
                                // 此处添加左侧导航逻辑
                            }
                    )
                
                // 右侧边缘拖拽区域(单独绑定手势)
                Color.gray.opacity(0.3)
                    .frame(width: 15)
                    .alignmentGuide(.trailing) { $0[.trailing] }
                    .gesture(
                        DragGesture()
                            .onChanged { value in
                                offset = value.translation.width
                            }
                            .onEnded { _ in
                                offset = 0.0
                                // 此处添加右侧导航逻辑
                            }
                    )
            }
        }
    }
}

#Preview {
    SwipeTest()
}

关键优化点

  1. 手势绑定范围限制:将拖拽手势直接附加到左右灰色边缘视图,只有触摸边缘时才会触发导航拖拽,完全不干扰列表项的侧滑操作。
  2. 替换屏幕宽度获取方式:用GeometryReader替代全局函数,更符合SwiftUI响应式设计,避免全局状态依赖。
  3. 移除全局手势:删除simultaneousGesture,彻底解决手势优先级冲突问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 03:45:11