为UIViewController中UIView的子视图添加Pan手势无响应求助
问题分析
你的dragView因为frame的x值等于父视图宽度,完全位于父视图的bounds之外。UIKit的触摸测试(hit-testing)机制默认只会识别视图自身bounds范围内的触摸事件,超出部分的触摸会被父视图或上层视图拦截,导致添加在dragView上的手势无法触发。
解决方案
步骤1:让父视图显示超出边界的子视图
在视图控制器的viewDidLoad中,将父视图的clipsToBounds设为false,确保dragView能在父视图外正常显示:
override func viewDidLoad() { super.viewDidLoad() notesView.clipsToBounds = false // 你的手势添加代码保持不变 let pan = UIPanGestureRecognizer(target: self, action: #selector(dragView(pan:))) pan.minimumNumberOfTouches = 1 pan.delegate = self notesView.dragView.addGestureRecognizer(pan) }
步骤2:修改父视图的触摸测试逻辑,让超出边界的dragView能接收触摸
在你的自定义父视图类(比如NotesView)中重写hitTest(_:with:)方法,手动判断触摸点是否落在dragView范围内,若是则将触摸事件传递给dragView:
class NotesView: UIView { @IBOutlet weak var dragView: UIView! override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { // 将触摸点转换到dragView的坐标系 let dragViewLocalPoint = convert(point, to: dragView) // 如果点在dragView的bounds内,返回dragView来响应触摸 if dragView.bounds.contains(dragViewLocalPoint) { return dragView } // 其他情况按默认逻辑处理 return super.hitTest(point, with: event) } }
额外检查项
- 确认
dragView.userInteractionEnabled为true(默认是开启状态,若被手动关闭需重新打开) - 确保没有其他视图或手势拦截了
dragView区域的触摸事件(比如父视图上的其他手势设置了cancelsTouchesInView = true)
内容的提问来源于stack exchange,提问作者PeculiarProgrammer
相关产品推荐
相关产品推荐

