iOS15+Xcode13下透明视图手势抢占UICollectionViewCell交互异常问题
iOS 15 透明父视图手势拦截子列表交互问题解决方案
问题根因
iOS 15 对 UIGestureRecognizer 触摸事件传递逻辑做了微调,提升了父视图手势的识别优先级,你场景中的透明视图 B 的点击手势识别阈值降低,会优先于子视图层级中的 UICollectionView 手势完成识别,进而拦截列表的点击、滚动事件,iOS 14 及更低版本无此逻辑变更因此运行正常。
布局示意图

可行解决方案
你可以任选以下一种方案修复:
- 方案1:重写透明视图 B 的
point(inside:with:)方法(推荐,适配性最高)
该方法可以直接控制视图是否响应对应区域的触摸事件,触摸点落在子视图区域内时直接透传事件,代码示例:// 重写B视图类的pointInside方法 override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { for subview in subviews { let convertedPoint = subview.convert(point, from: self) if subview.point(inside: convertedPoint, with: event) { return false } } return super.point(inside: point, with: event) } - 方案2:实现手势代理方法控制手势响应范围
给 B 的点击手势设置代理,实现gestureRecognizer(_:shouldReceive:)方法,仅当触摸点落在 B 本身无其他子视图的区域时才响应手势:
首先设置手势代理:
然后实现代理方法:let tap = UITapGestureRecognizer(target: self, action: #selector(dismisClicked(_:))) tap.delegate = self bView.addGestureRecognizer(tap)func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { let touchPoint = touch.location(in: bView) return !cView.frame.contains(touchPoint) } - 方案3:设置手势优先级
将 UICollectionView 的交互手势优先级设置为高于 B 的点击手势,让列表手势优先识别:// 让B的点击手势等待列表手势识别失败后再触发 if let collectionGestures = collectionView.gestureRecognizers { for gesture in collectionGestures { bTapGesture.require(toFail: gesture) } }
内容的提问来源于stack exchange,提问作者Salar Pro
相关产品推荐
相关产品推荐

