全屏 UIView 子类作为面纱不消耗触摸事件

Posted

技术标签:

【中文标题】全屏 UIView 子类作为面纱不消耗触摸事件【英文标题】:Full-screen UIView subclass as veil not consuming touch events 【发布时间】:2011-03-04 20:30:16 【问题描述】:

我有一个可以运行的标签栏应用。每个选项卡都是一个UINavigationController,其根视图是某种UIViewController,通常是UITableViewController

在应用程序中的某些情况下,我想显示一个全屏“面纱”,其中包含有关正在发生的事情的消息,直到某些操作完成。关键是要吞下 UI 上的任何触摸,这些触摸会远离操作开始的位置。

面纱是 UIView 的子类。该类有一个单例实例。显示时,我将其作为UITabBarController 视图的子视图插入。该视图出现在整个 UI 上,包括标签栏。太好了!

这就是问题所在。我可以点击选项卡并更改 UI。我所期望的是,我的面纱视图会吞噬这些触摸。

我已经在我的面纱类中实现了各种触摸Began|Ended|Moved|Canceled 方法(作为无操作方法),但触摸仍然被标签栏拾取,坦率地说,被任何对象下的任何地方拾取我碰巧碰到了。

我也尝试过覆盖许多其他方法,包括 nextResponder、hitTest:withEvent: 等,但均无济于事。

在这一点上我有点难过。我希望有人能给一些圣人的建议。 :-)

谢谢。

【问题讨论】:

【参考方案1】:

修改框架类的视图层次结构是不安全的。只需将其添加为窗口本身的子视图,您会得到更好的服务。至于消费触摸,如果进行此更改不起作用,那么您还应该验证 userInteractionEnabled 在视图上设置为 YES。您不必实际实现任何与触摸相关的方法。

【讨论】:

@Kevin-Ballard:谢谢。因此,我按照您的建议实现了相同的视觉效果:将面纱插入为代表窗口的子视图。并且,面纱的userInteractionEnabled 标志设置为YES。我注释掉了我的触摸处理方法的空实现。触摸继续传递到底层视图。还有其他想法吗? @MarkGranoff:我认为如果您将空实现留在原地,它也会失败?你把它插在窗口的根部?对于您的行为,我能想到的最可能的原因是,如果超级视图具有 UIGestureRecognizer,但如果您位于窗口的根目录,则情况并非如此。我唯一能想到的就是你的阿尔法。您是否在视图中设置了 alpha 属性?如果alpha 等于或小于0.05,则触摸跳过视图。它应该设置为1,并且您的视图应该没有背景颜色。 @Kevin-Ballard:是的,有或没有 null 实现,相同的行为。没有使用 UIGestureRecognizers,至少我没有明确表示。 alpha 属性已设置,但设置为 0.65。所以我将它设置为 1,并使用 clearColor 以便我可以看到可能发生的情况。仍然失败。顺便说一句,视图是用类似[[myApp delegate].window addSubview:[Veil theVeil]] 的代码插入的。这当然有效(我看到了面纱),而且我想不出另一种“正确的方式”来做到这一点。真的很奇怪。 @Kevin-Ballard:哦,我还为面纱视图设置了ExclusiveTouch 为YES,我认为这肯定可以解决问题,但它没有效果。 @MarkGranoff: setExclusiveTouch 实际上并没有按照你的想法去做。它与如何处理多个触摸事件有关,对单次触摸没有任何影响。【参考方案2】:

我也遇到了这个问题,并想出了一个 hacky 解决方案。在自定义 UIView 类的 init 中,创建一个无法命中的虚拟 UIView,例如 [[UIView alloc] initWithFrame:CGRectMake(-1, -1, 0, 0)]。或者实际上,我认为任何未附加到窗口的 UIView 都有效。然后,在hitTest:withEvent: 中,让它为您感兴趣的区域之外的每个点返回虚拟视图。

【讨论】:

以上是关于全屏 UIView 子类作为面纱不消耗触摸事件的主要内容,如果未能解决你的问题,请参考以下文章

uiscrollview 和 uibutton 对触摸事件透明

UIControl 子类 - 如何停止触摸事件流?

UIScrollview 窃取触摸事件

iOS - 背景视图正在消耗触摸事件

使触摸在 UIView 子类中留下发光的痕迹

iOS - 过滤和转发触摸到子视图