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

如何在SwiftUI中使用多个UIGestureRecognizer实现手势同时识别

问题根因

你的两个手势分别附加在ZStack中的同级UIView上,iOS触摸事件默认只会传递给最上层的响应视图,下层视图的手势根本接收不到触摸事件,自然无法触发,即使各自的手势代理返回允许同时识别也不会生效。

可行解决方案

步骤1:自定义透传触摸的UIView子类

重写hitTest方法让视图不成为触摸响应者,但是保留手势识别能力,触摸事件会自动透传给下层的其他视图:

class GestureCaptureView: UIView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        return nil
    }
}

步骤2:修改两个手势视图的实现

分别替换DragGestureView和TwoFingerNavigationView中的默认UIView为上述自定义视图,同时给手势添加cancelsTouchesInView = false避免拦截其他手势的事件。

修改后的DragGestureView的makeUIView方法:

public func makeUIView(context: UIViewRepresentableContext<DragGestureView>) -> UIView {
    let view = GestureCaptureView(frame: .zero)
    view.backgroundColor = .clear
    let gesture = UIPanGestureRecognizer(target: context.coordinator,
                                         action: #selector(Coordinator.dragged))
    gesture.minimumNumberOfTouches = 1
    gesture.maximumNumberOfTouches = 1
    gesture.delegate = delegate
    gesture.cancelsTouchesInView = false
    view.addGestureRecognizer(gesture)
    return view
}

对TwoFingerNavigationView的makeUIView做完全相同的修改即可。

可选交互优化(适配绘图类应用逻辑)

为了避免双指操作时误触发单指绘制逻辑,可以在单指手势的回调开头添加触摸数量判断:

@objc func dragged(gesture: UIPanGestureRecognizer) {
    // 双指操作时不触发单指绘制逻辑
    guard gesture.numberOfTouches == 1 else { return }
    if gesture.state == .ended {
        self.dragEndedCallback()
    } else {
        self.draggedCallback(gesture.location(in: gesture.view))
    }
}

修改完成后两个手势就能按照你的预期正常触发,不需要调整ZStack的层级顺序,也不影响下层画布内容的交互。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 05:45:02