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

Mar*_*ons 3 hierarchy touch uiview ios swift

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

在此输入图像描述

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

这似乎是一个等级问题。我努力了:

  1. 调整 Z 索引
  2. 将整个 UITableView 放置在 Storyboard 层次结构中父级的外部,但在视觉上将其放置在父级的内部。

我不知道如何继续。

编辑:

请参阅安德里亚的答案,这对我有用。我最终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
}
Run Code Online (Sandbox Code Playgroud)

And*_*rea 7

正如唐·马格所写:

您无法与超出其父级(超级视图)范围的元素进行交互。

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

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

func point(inside point: CGPoint, 
      with event: UIEvent?) -> Bool
Run Code Online (Sandbox Code Playgroud)

这些方法必须被重写,我已经在我的方法上粘贴了一些代码,它已经很旧了,因此可能需要从 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)
    }
}
Run Code Online (Sandbox Code Playgroud)


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