持续动画重叠UIView的点击、双击及滑动手势识别异常问题咨询
触控事件识别异常修复方案
问题需求
需要支持3种手势交互:
- 用户单击视图时单击手势可被正确识别
- 用户双击视图时双击手势可被正确识别
- 用户在屏幕上滑动手指时,若手指下方存在对应视图,可正确触发选中识别
现有异常表现
多个UIView处于持续动画状态且可能出现重叠,已按视图尺寸排序,最小的视图层级位于更大的视图上方。点击视图时经常无法被识别,尤其是双击手势;滑动操作大多数时候运行正常,但整体交互体验非常不稳定。
核心问题根因
- 动画场景坐标检测错误:动画过程中
UIView.frame存储的是动画结束后的最终坐标,hitTest默认基于当前展示的presentation层坐标判断,现有逻辑直接读取视图frame导致命中判断失效。 - 手势配置错误:现有代码中
BoxView初始化时,给自定义单击/双击手势传入的响应方法均为双击处理方法,单击逻辑本身没有对应实现。 - 事件链拦截:父视图
FinderrBoxView重写了touchesBegan、touchesMoved方法但没有调用父类实现,导致事件没有透传给子视图的手势识别器,子视图手势无法接收事件。 - 视图频繁重建:
drawBoxs方法中频繁移除、新建BoxView实例,刚添加的手势还未完成识别流程,视图就被销毁导致识别失效。
修复代码
1. 重写BoxView的hitTest适配动画场景
class BoxView: UIView { // 原有逻辑保持不变 override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { guard let presentationLayer = layer.presentation() else { return super.hitTest(point, with: event) } let presentationFrame = presentationLayer.frame return presentationFrame.contains(point) ? self : nil } }
2. 修正手势配置与事件透传
// BoxView初始化修正 init(frame: CGRect, itemName: String) { self.itemName = itemName super.init(frame: frame) if !UIAccessibility.isVoiceOverRunning { let singleDoubleTapRecognizer = SingleDoubleTapGestureRecognizer( target: self, singleAction: #selector(handleSingleTapGesture), // 绑定单击响应方法 doubleAction: #selector(handleDoubleTapGesture) ) singleDoubleTapRecognizer.cancelsTouchesInView = false addGestureRecognizer(singleDoubleTapRecognizer) } } // 新增单击响应方法 @objc func handleSingleTapGesture(_: UITapGestureRecognizer) { // 单击处理逻辑 } // FinderrBoxView触摸事件透传修正 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { processTouches(touches, with: event) super.touchesBegan(touches, with: event) } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { processTouches(touches, with: event) super.touchesMoved(touches, with: event) }
3. 优化视图复用逻辑
调整drawBoxs与update方法逻辑,优先复用已有BoxView实例,仅当没有可复用视图时才新建实例,避免频繁销毁重建视图。
额外优化建议
可以调整自定义双击手势的超时时间为0.3s,符合iOS系统默认双击识别间隔,提升双击识别准确率。
内容的提问来源于stack exchange,提问作者Ferdinand Lösch
相关产品推荐
相关产品推荐

