同一UIView中两个UIPanGestureRecognizer能否同时触发?
在同一UIView中实现双UIPanGestureRecognizer同时触发的方案
核心疑问解答
在同一个UIView中同时触发两个UIPanGestureRecognizer完全可行,但需要精准控制触摸事件的分配逻辑,你的问题出在触摸事件的归属判定上。
当前问题原因
第一个手势激活后,系统会默认将后续触摸事件优先分配给已处于活跃状态的手势。即使第二个触摸点落在另一区域,由于你的shouldReceive touch方法直接返回true,没有限制每个手势只能接收对应区域的触摸,导致第二个触摸被已活跃的手势“占用”,无法触发第二个手势。
解决方案
通过手势代理的shouldReceive touch方法,为每个手势过滤触摸点:只让panGesture1接收视图上半区的触摸,panGesture2接收下半区的触摸。同时保留shouldRecognizeSimultaneouslyWith返回true,确保两个手势可以同时激活。
优化后的完整代码如下:
class YourViewController: UIViewController, UIGestureRecognizerDelegate { let panGesture1 = UIPanGestureRecognizer() let panGesture2 = UIPanGestureRecognizer() override func viewDidLoad() { super.viewDidLoad() // 配置panGesture1 panGesture1.addTarget(self, action: #selector(panGesture1Detected(_:))) panGesture1.delegate = self panGesture1.minimumNumberOfTouches = 1 panGesture1.maximumNumberOfTouches = 1 panGesture1.cancelsTouchesInView = false panGesture1.delaysTouchesBegan = false panGesture1.delaysTouchesEnded = true panGesture1.requiresExclusiveTouchType = false view.addGestureRecognizer(panGesture1) // 配置panGesture2 panGesture2.addTarget(self, action: #selector(panGesture2Detected(_:))) panGesture2.delegate = self panGesture2.minimumNumberOfTouches = 1 panGesture2.maximumNumberOfTouches = 1 panGesture2.cancelsTouchesInView = false panGesture2.delaysTouchesBegan = false panGesture2.delaysTouchesEnded = true panGesture2.requiresExclusiveTouchType = false view.addGestureRecognizer(panGesture2) } // 允许两个手势同时识别 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } // 限制手势仅在对应区域开始触发 func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { let touchY = gestureRecognizer.location(in: view).y let midY = view.bounds.midY if gestureRecognizer == panGesture1 { return touchY < midY } else if gestureRecognizer == panGesture2 { return touchY > midY } return false } // 过滤每个手势能接收的触摸点 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { let touchY = touch.location(in: view).y let midY = view.bounds.midY if gestureRecognizer == panGesture1 { return touchY < midY } else if gestureRecognizer == panGesture2 { return touchY > midY } return false } // 手势触发回调 @objc func panGesture1Detected(_ gesture: UIPanGestureRecognizer) { // 处理上半区拖拽逻辑 } @objc func panGesture2Detected(_ gesture: UIPanGestureRecognizer) { // 处理下半区拖拽逻辑 } }
对临时思路的评估
添加空UIView分隔区域的方法可行:将上半区的空视图绑定panGesture1,下半区绑定panGesture2,系统会自动根据触摸点所在视图分配事件,无需复杂的代理逻辑。但这种方式会增加视图层级,如果你希望保持视图结构简洁,使用上述代理方法更优。
内容的提问来源于stack exchange,提问作者Gizmodo
相关产品推荐
相关产品推荐

