我有一个UIView,它位于所有其他视图之上,并且已经覆盖了hitTest()方法,该方法总是返回自己:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
return self
}
然后,当我使用touchesBegan()中的点进行一些操作时,我需要将hitTest()传递给我们的UIView下面的视图:
override public func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// Do some operations
// ...
// ...
// ...
// pass touch event handling to views below or change hitTest()
}
所以基本上,在顶部UIView我重写了touchesBegan(),touchesMoved()和touchesEnded()方法。然后我需要处理触摸,执行一些操作,然后,如果需要,传递给下面的视图。有可能吗?
答案 0 :(得分:1)
以不同的方式解决您的问题可能更简单,更好。
UIKit通过在sendEvent(_:)
消息中将其发送到窗口(视图层次结构的根目录)来提供触摸事件。窗口的sendEvent(_:)
方法负责查找对触摸感兴趣的手势识别器,并将适当的touchesBegan
,touchesMoved
等消息发送给识别器和/或点击视图。
这意味着您可以继承UIWindow
并覆盖sendEvent(_:)
,以便在事件到达任何手势识别器或视图之前查看窗口中的每个触摸事件,而不会覆盖任何视图&#39; s hitTest(_:with:)
方法。然后将事件传递到super.sendEvent(event)
以进行正常路由。
示例:
class MyWindow: UIWindow {
override func sendEvent(_ event: UIEvent) {
if event.type == .touches {
if let count = event.allTouches?.filter({ $0.phase == .began }).count, count > 0 {
print("window found \(count) touches began")
}
if let count = event.allTouches?.filter({ $0.phase == .moved }).count, count > 0 {
print("window found \(count) touches moved")
}
if let count = event.allTouches?.filter({ $0.phase == .ended }).count, count > 0 {
print("window found \(count) touches ended")
}
if let count = event.allTouches?.filter({ $0.phase == .cancelled }).count, count > 0 {
print("window found \(count) touches cancelled")
}
}
super.sendEvent(event)
}
}
您可以在应用中使用此窗口子类,方法是将应用代理的window
商店初始化为其实例,如下所示:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? = MyWindow()
// other app delegate members...
}
请注意,UIKit在触摸开始时使用hitTest(_:with:)
设置触摸的view
属性,之前将触摸开始事件传递到窗口。 UIKit还将每个触摸的gestureRecognizers
属性设置为可能需要触摸的识别器集(识别器状态.possible
)或正在使用触摸(状态began
,{{在将事件传递给窗口changed
之前,1}},ended
,cancelled
)。因此,如果需要知道触摸的位置,sendEvent(_:)
覆盖可以查看每个触摸的sendEvent(_:)
属性。