如何在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
相关产品推荐
相关产品推荐

