触摸事件不会在部分扩展到父 UIView 之外的子 UIView 之外注册
Touch event does not register outside of a child UIView that partially extends outside of parent UIView
我有一个包含两个元素的父视图。本质上,它们包含一个下拉菜单 select。参考下图:单击蓝色元素时,它会显示一个(最初隐藏的)下拉 UITableView。此 UITableView 部分位于还包含蓝色元素的同一父视图内。
当我尝试单击其中一个 UITableViewCells 时,只有第一个单元格注册了触摸事件。如果 table 视图的位置使得第一个单元格部分位于父级内部,则仅单击父级寄存器内部的图像的一半。
这似乎是一个等级问题。我试过:
- 调整 Z 指数
- 将整个 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 相关,您应该使用选择器。
我有一个包含两个元素的父视图。本质上,它们包含一个下拉菜单 select。参考下图:单击蓝色元素时,它会显示一个(最初隐藏的)下拉 UITableView。此 UITableView 部分位于还包含蓝色元素的同一父视图内。
当我尝试单击其中一个 UITableViewCells 时,只有第一个单元格注册了触摸事件。如果 table 视图的位置使得第一个单元格部分位于父级内部,则仅单击父级寄存器内部的图像的一半。
这似乎是一个等级问题。我试过:
- 调整 Z 指数
- 将整个 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 相关,您应该使用选择器。