如何在透明的UIView后面点击按钮?

202
假设我们有一个视图控制器和一个子视图。子视图在屏幕中心占据位置,并在四周留出100像素的边距。然后我们添加了一堆小东西在这个子视图里面可以点击。我们只是利用子视图来利用新的框架(在子视图内部x=0,y=0实际上是在父视图中的100,100)。
然后,想象一下我们在子视图后面放置了某些东西,比如菜单。我希望用户能够选择子视图中的任何“小东西”,但如果没有,则希望触摸事件可以穿过子视图(因为背景本来就是透明的),传递到其后面的按钮。
我该怎么做呢?看起来touchesBegan可以通过,但按钮却不起作用。

1
我以为透明的(alpha 0)UIView不应该响应触摸事件? - Evadne Wu
1
我写了一个小类专门处理这个问题。(在答案中添加了一个示例)。那里的解决方案比被接受的答案要好一些,因为你仍然可以点击半透明的UIView下面的UIButton,而UIView不透明的部分仍然会响应触摸事件。 - Segev
注意:自iOS 14以来,UIStackView是一个渲染视图。这意味着它可以有一个背景。即使它是.clear颜色,它也不会将触摸事件传递给底层视图。 - heyfrank
16个回答

1
据我所知,您应该可以通过覆盖hitTest:方法来实现这一点。我尝试过了,但无法使其正常工作。
最终,我创建了一系列透明视图,围绕可触摸对象,以便它们不会覆盖它。对于我的问题来说,这有点像一个hack,但效果很好。

1
借鉴其他答案的提示并阅读苹果文档,我为解决您的问题创建了这个简单的库:
https://github.com/natrosoft/NATouchThroughView
它使得在Interface Builder中绘制视图变得容易,可以将触摸事件传递到底层视图。
我认为方法交换在生产代码中是过度的,非常危险,因为你直接干扰Apple的基本实现,可能会导致意外后果。
有一个演示项目,希望README能很好地解释该怎么做。要解决OP(原始帖子),您需要在Interface Builder中将包含按钮的清晰UIView更改为NATouchThroughView类。然后找到覆盖想要点击的菜单的空白UIView。在Interface Builder中将该UIView更改为NARootTouchThroughView类。它甚至可以是视图控制器的根UIView,如果您打算将这些触摸事件传递到底层视图控制器。查看演示项目以了解其工作原理。它非常简单,安全,并且不会对系统做出侵入性修改。

0
尝试一下。
class PassthroughToWindowView: UIView {
        override func test(_ point: CGPoint, with event: UIEvent?) -> UIView? {
            var view = super.hitTest(point, with: event)
            if view != self {
                return view
            }

            while !(view is PassthroughWindow) {
                view = view?.superview
            }
            return view
        }
    } 

0

我使用这个方法而不是重写 point(inside: CGPoint, with: UIEvent) 方法

  override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard self.point(inside: point, with: event) else { return nil }
        return self
    }

0
尝试将transparentViewbackgroundColor设置为UIColor(white:0.000, alpha:0.020)。然后你就可以在touchesBegan/touchesMoved方法中获取触摸事件。将以下代码放置在视图初始化的某个位置:
self.alpha = 1
self.backgroundColor = UIColor(white: 0.0, alpha: 0.02)
self.isMultipleTouchEnabled = true
self.isUserInteractionEnabled = true

-1

如果您不想使用类别或子类UIView,您也可以将按钮前置,使其位于透明视图的前面。这取决于您的应用程序,这并不总是可能的,但对我而言有效。您始终可以再次将按钮带回或隐藏它。


2
你好,欢迎来到Stack Overflow。作为新用户,我有一个小提示:你可能需要注意自己的语气。我建议避免使用“如果你不想费心”的这类措辞,因为它可能会显得有些轻蔑。 - nomistic
谢谢提醒。这更多是出于懒惰的角度而非轻蔑,但我明白了。 - Shaked Sayag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接