如何将UITableView默认平移手势传递至另一个UIView?
实现UITableView空白区域触发底层视图的平移手势
要实现这个需求,核心是让UITableView在空白区域不拦截触摸事件,将事件传递给下方带UIPanGestureRecognizer的UIView,下面提供两种可行方案:
方案一:子类化UITableView重写hitTest方法
通过重写hitTest(_:with:)方法,判断触摸点是否落在UITableView的空白区域(即未命中任何cell、header、footer),如果是则返回nil,让事件继续向下传递给底层视图。
class PassThroughTableView: UITableView { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let hitView = super.hitTest(point, with: event) // 仅当命中视图是tableView本身时(空白区域),才放弃响应权 if hitView === self { return nil } return hitView } }
使用时,将原代码中的UITableView替换为这个自定义子类即可,无需额外配置。
方案二:利用UIGestureRecognizerDelegate控制触摸接收
给底层视图的UIPanGestureRecognizer设置代理,通过gestureRecognizer(_:shouldReceive:)方法判断触摸点是否在UITableView的有效内容区域(cell、header、footer),如果不在则允许平移手势响应。
extension YourViewController: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { guard let tableView = touch.view as? UITableView else { return true } let touchPoint = touch.location(in: tableView) // 判断是否点击在cell上 if tableView.indexPathForRow(at: touchPoint) != nil { return false } // 可选:判断是否点击在header/footer上,按需屏蔽 let sectionCount = tableView.numberOfSections for section in 0..<sectionCount { let headerRect = tableView.rectForHeader(inSection: section) if headerRect.contains(touchPoint) { return false } let footerRect = tableView.rectForFooter(inSection: section) if footerRect.contains(touchPoint) { return false } } // 空白区域,允许平移手势响应 return true } }
记得在初始化平移手势时设置代理:
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) panGesture.delegate = self yourUnderlyingView.addGestureRecognizer(panGesture)
方案对比
- 方案一:代码简洁,全局生效,适合所有使用该子类的UITableView都需要此行为的场景。
- 方案二:无需子类化,灵活性高,可针对单个平移手势做精细化控制,比如单独处理header/footer的触摸逻辑。
内容的提问来源于stack exchange,提问作者Kazi Abdullah Al Mamun
相关产品推荐
相关产品推荐

