iOS UIKit项目中TableView超出父视图范围触摸无响应问题求助
解决UIKit中子视图超出父视图范围触摸无响应问题
问题根源
UIKit的触摸事件传递逻辑里,父视图会先判断触摸点是否落在自身bounds范围内。默认情况下,若触摸点不在父视图bounds内,父视图会直接返回nil,不会把事件传递给子视图。你的场景中,父视图A的frame是(0, 0, 320, 200),子视图B的范围超出了A的bounds,所以超出部分的触摸事件被A拦截,无法传递到B内部的TableView,导致对应区域无响应。
解决方案
重写父视图A的hitTest(_:with:)方法,让它把超出自身bounds的触摸事件传递给子视图B:
class ViewA: UIView { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let originalHitView = super.hitTest(point, with: event) if originalHitView === self { // 倒序遍历子视图,确保层级靠上的视图优先响应 for subview in subviews.reversed() { let convertedPoint = subview.convert(point, from: self) if let hitSubview = subview.hitTest(convertedPoint, with: event) { return hitSubview } } return nil } return originalHitView } }
如果场景中只有View B这一个子视图需要处理,也可以简化逻辑:
class ViewA: UIView { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { guard let viewB = subviews.first(where: { $0 is ViewB }) as? ViewB else { return super.hitTest(point, with: event) } let pointInViewB = viewB.convert(point, from: self) if viewB.bounds.contains(pointInViewB) { return viewB.hitTest(pointInViewB, with: event) } return super.hitTest(point, with: event) } }
补充说明
如果业务允许,你也可以调整父视图A的frame,或者通过AutoLayout让A的大小适配B的范围,这样就不需要重写hitTest。但如果必须保持A的frame不变,重写触摸事件传递逻辑是最直接的解决方式。
内容的提问来源于stack exchange,提问作者Ravi kiran
相关产品推荐
相关产品推荐

