触摸事件不会在部分扩展到父 UIView 之外的子 UIView 之外注册

Touch event does not register outside of a child UIView that partially extends outside of parent UIView

我有一个包含两个元素的父视图。本质上,它们包含一个下拉菜单 select。参考下图:单击蓝色元素时,它会显示一个(最初隐藏的)下拉 UITableView。此 UITableView 部分位于还包含蓝色元素的同一父视图内。

当我尝试单击其中一个 UITableViewCells 时,只有第一个单元格注册了触摸事件。如果 table 视图的位置使得第一个单元格部分位于父级内部,则仅单击父级寄存器内部的图像的一半。

这似乎是一个等级问题。我试过:

  1. 调整 Z 指数
  2. 将整个 UITableView 置于情节提要层次结构中的父级外部,但在视觉上将其定位在其中。

我不确定如何进行。

编辑:

查看对我有用的 Andrea 回答。我最终按照建议覆盖了 point 方法,并没有使用 hitTest。但是,我使用了 point 方法重写的另一个实现:

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    if super.point(inside: point, with: event) { return true }
    for subview in subviews {
        let subviewPoint = subview.convert(point, from: self)
        if subview.point(inside: subviewPoint, with: event) { return true }
    }
    return false
}

正如 DonMag 所写:

You cannot interact with an element that extends beyond the bounds of its parent (superview).

至少在重写一些方法的情况下,视图有自己的实现来检测触摸。最重要的方法是:

func hitTest(_ point: CGPoint, 
        with event: UIEvent?) -> UIView?

func point(inside point: CGPoint, 
      with event: UIEvent?) -> Bool

必须覆盖这些方法,我已经在我的代码上粘贴了一些代码,这些代码很旧,因此可能需要 swift 从 3.x 迁移到 4.x。您将添加为子视图的所有内容都将处理触摸,即使在边界之外也是如此:

class GreedyTouchView: UIView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if !self.clipsToBounds && !self.isHidden && self.alpha > 0.0 {
            let subviews = self.subviews.reversed()
            for member in subviews {
                let subPoint = member.convert(point, from: self)
                if let result: UIView = member.hitTest(subPoint, with:event) {
                    return result
                }
            }
        }
        return super.hitTest(point, with: event)
    }
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        return super.point(inside: point, with: event)
    }
}


但我想指出的是,下拉菜单更多的是 Web UI 相关而不是 iOS UI 相关,您应该使用选择器。