You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 04:48:02