swift - UIView 捕捉触摸事件并传递

标签 swift uiview touches

我想实现 UIView 子类,它将捕获所有触摸事件(尤其是 touchesMoved)并传递它们。可能吗?

class PassthroughView: UIView {

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let view = super.hitTest(point, with: event)
        return view == self ? nil : view
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touchesBegan")
        super.touchesBegan(touches, with: event)
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touchesMoved") //not called
        super.touchesMoved(touches, with: event)
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touchesEnded")
        super.touchesEnded(touches, with: event)
    }
}

最佳答案

你真的不能这样做。如果您的 View 接收到触摸,它无法将其传递给如果您的 View 不存在时本应接收到的 View 。为此,您基本上必须重新实现整个事件路由。如果不访问 Apple 内部 API,这将非常困难,甚至可能是不可能的。但即使你做对了,它也可能会随着每次 iOS 更新而中断。

但是有一种不同的方法可以获取所有触摸事件,同时仍然将它们传送到适当的 View 。为此,您创建了 UIApplication 的子类并覆盖了 sendEvent(_:) 方法。这是为每个事件调用并将其分派(dispatch)到适当的 View 。从那里您可以首先进行特殊处理,然后像往常一样调用 super.sendEvent() 将其发送到您的窗口。

当然,您不会收到触摸开始/移动/结束的不同调用,但信息存在于您的事件对象中。首先,您需要检查 event.type 属性以查看您是否确实获得了触摸事件。如果是这样,您可以从 event.allTouches 属性中获取所有触摸。对于每次触摸,您可以获得 phase,它描述了此触摸是否开始、移动、结束等。

当然子类化是不够的,你还必须告诉系统使用你的新子类。为此,您将其注释为 @objc(MyApplication),其中 MyApplication 是类的名称。这确保 Objective-C 运行时可以通过您给它的名称找到该类。然后编辑 Info.plist 文件并为“Principal class”键设置这个名称。 (如果您不使用 Xcode 编辑器,该 key 也称为 NSPrincipalClass)。

关于swift - UIView 捕捉触摸事件并传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49615930/

相关文章:

ios - 排除在 Assets 中使用 1x 的设备

ios - 捕获完成后从 AVCapturePhotoOutput 获取使用的曝光持续时间和 ISO 值

ios - UITableViewRowAnimationNone - 表现为 UITableViewRowAnimation(顶部/底部)

ios - 创建自定义 UINavigationcontroller 类

ios - Swift 中 View 相对于另一个 View 的位置

ios - 如何像 Apple Music 处理专辑封面那样从图像中获取背景和文本颜色?

iphone - 在两个 UIView 之间应用混合模式的最简单/最快的方法

ios - 多点触控时 UITouches "lost"

swift - Sprite Kit 中的多点触控手势