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

加载遮罩用带透明度UIView时点击事件穿透至底层按钮的问题

解决半透明遮罩UIView点击穿透底层按钮的问题

这个问题我之前也碰到过,本质是iOS的触摸事件传递机制在起作用:你的半透明遮罩虽然视觉上覆盖了全屏,但因为它没有处理触摸事件,系统会把触摸继续向下传递给底层的可交互控件(比如你的按钮)。

下面给你两种简单可行的解决方法,选哪种都能解决问题:

方法1:自定义遮罩视图拦截触摸

创建一个UIView的子类,重写hitTest(_:with:)方法让它直接返回自身,这样所有落在遮罩上的触摸都会被拦截,不会传递到底层视图:

class LoadingMaskView: UIView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        // 强制拦截所有触摸事件,阻止向下传递
        return self
    }
}

然后把你原来的UIView替换成这个自定义类就行:

let loadingView = LoadingMaskView() 
loadingView.tag = 9999 
loadingView.frame = UIScreen.main.bounds // 简化写法,直接用屏幕边界
loadingView.backgroundColor = UIColor.white.withAlphaComponent(0.4)
controller.view.addSubview(loadingView)

方法2:添加空点击手势(无需自定义类)

如果不想自定义子类,也可以给遮罩视图加一个空的点击手势识别器——系统会认为遮罩已经处理了触摸事件,就不会再把事件向下传递了:

let loadingView = UIView() 
loadingView.tag = 9999 
loadingView.frame = UIScreen.main.bounds
loadingView.backgroundColor = UIColor.white.withAlphaComponent(0.4)

// 添加空的点击手势
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(emptyMaskTapHandler))
loadingView.addGestureRecognizer(tapGesture)

controller.view.addSubview(loadingView)

// 实现空的处理方法
@objc private func emptyMaskTapHandler() {
    // 什么都不用做,只是用来拦截触摸事件
}

补充说明

为什么原来的遮罩会穿透?因为默认情况下,UIView如果没有绑定任何触摸事件处理(比如手势、重写触摸方法),系统会判定它不需要处理触摸,于是就把事件继续传递给下层能处理的视图。通过上面两种方法,我们相当于告诉系统“这个遮罩要接管触摸”,自然就能阻止事件穿透了。

内容的提问来源于stack exchange,提问作者r_honey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:38:15