Swift中如何捕获全局触摸抬起事件且不影响子视图事件处理?
解决全局捕获触摸抬起事件且不影响子视图事件的问题
问题原因
你添加的UILongPressGestureRecognizer设置了minimumPressDuration = 0,会在触摸开始时就抢占触摸事件,即便设置了shouldRecognizeSimultaneouslyWith返回true,仍会干扰UIControl(如UIButton)的目标事件响应逻辑,导致子视图的addTarget事件失效。
解决方案一:重写视图触摸事件方法(推荐)
利用UIKit触摸事件的冒泡机制,直接在ViewController的view中重写touchesEnded方法。子视图的触摸事件会先被处理,之后事件会传递到父视图,既不影响子视图功能,又能全局捕获触摸抬起事件。
修改后代码:
override func viewDidLoad() { let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50)) button.setTitle("Click me", for: .normal) button.backgroundColor = .blue // 添加背景色便于点击测试 button.addTarget(self, action: #selector(buttonClick), for: .touchDown) self.view.addSubview(button) // 无需再添加UILongPressGestureRecognizer } // 重写view的触摸结束方法 override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesEnded(touches, with: event) print("Detect global touch end / up") } @objc func buttonClick() { print("CLICK") // 可正常触发 }
解决方案二:优化手势识别器配置
若必须使用手势识别器,需调整代理逻辑并修改手势属性,确保UIControl事件优先响应的同时,手势能正常捕获触摸结束:
extension YourViewController: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } // 允许全局手势与UIControl手势同时响应,无需等待UIControl手势失败 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool { return otherGestureRecognizer is UIControlGestureRecognizer } } override func viewDidLoad() { let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50)) button.setTitle("Click me", for: .normal) button.backgroundColor = .blue button.addTarget(self, action: #selector(buttonClick), for: .touchDown) self.view.addSubview(button) initLongTapGesture() } func initLongTapGesture () { let globalTap = UILongPressGestureRecognizer(target: self, action: #selector(tapHandler)) globalTap.delegate = self globalTap.minimumPressDuration = 0 // 关闭手势的触摸事件独占性,避免阻断子视图事件 globalTap.cancelsTouchesInView = false self.view.addGestureRecognizer(globalTap) } @objc func tapHandler(gesture: UILongPressGestureRecognizer) { if [.ended, .cancelled, .failed].contains(gesture.state) { print("Detect global touch end / up") } } @objc func buttonClick() { print("CLICK") // 可正常触发 }
内容的提问来源于stack exchange,提问作者AleXiuS
相关产品推荐
相关产品推荐

