【问题标题】:Call hitTest inside of touchesMoved在 touchesMoved 中调用 hitTest
【发布时间】:2018-02-09 23:37:02
【问题描述】:

我有一个 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() 方法。然后我需要处理触摸,执行一些操作,然后,如果需要,传递到下面的视图。有可能吗?

【问题讨论】:

    标签: ios swift uiview


    【解决方案1】:

    以不同的方式解决您的问题可能更简单更好。

    UIKit 通过在sendEvent(_:) 消息中将触摸事件发送到窗口(视图层次结构的根)来传递触摸事件。窗口的sendEvent(_:) 方法负责查找对触摸感兴趣的手势识别器,并向识别器和/或命中视图发送相应的touchesBegantouchesMoved 等消息。

    这意味着您可以继承 UIWindow 并覆盖 sendEvent(_:) 以在事件到达任何手势识别器或视图之前查看窗口中的每个触摸事件,而无需覆盖任何视图的 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)或正在积极使用触摸(状态beganchangedendedcancelled)的识别器集在将事件传递给窗口的sendEvent(_:) 之前。所以你的sendEvent(_:) 覆盖可以查看每个触摸的view 属性,如果它需要知道触摸的去向。

    【讨论】:

    • 谢谢!这种方法似乎对我的任务很有帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多