UIView 捕获触摸事件并传递

问题描述 投票:0回答:3

我想实现

UIView
子类,它将捕获所有触摸事件(尤其是 TouchMoved)并传递它们。可以吗?

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)
    }
}
swift uiview touches
3个回答
2
投票

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

但是有一种不同的方法来获取所有触摸事件,同时仍然将它们传递到适当的视图。为此,您创建

UIApplication
的子类并重写
sendEvent(_:)
方法。每个事件都会调用此方法并将其分派到适当的视图。从那里您可以先进行特殊处理,然后调用
super.sendEvent()
将其像往常一样发送到您的窗口。

当然,您不会收到不同的触摸开始/移动/结束调用,但信息存在于您的事件对象中。首先,您需要检查

event.type
属性以查看是否确实收到了触摸事件。如果是这样,您可以从
event.allTouches
属性获取所有触摸。对于每次触摸,您都可以获得
phase
,它描述了此触摸是否开始、移动、结束等。

当然子类化还不够,你还必须告诉系统使用你的新子类。为此,您将其注释为

@objc(MyApplication)
,其中
MyApplication
是类的名称。这可以确保 Objective-C 运行时可以通过您指定的名称找到该类。然后编辑 Info.plist 文件并将此名称设置为“Principal class”键。 (如果您不使用 Xcode 编辑器,该键也称为
NSPrincipalClass
)。


0
投票

我使用这个类:

class TouchlessView: UIView {

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        let buttons = findViews(subclassOf: UIButton.self)
        for button in buttons where button.frame.contains(point) {
            return true
        }
        return false
    }
}

-1
投票

我在视图中添加了平移手势识别器。

© www.soinside.com 2019 - 2024. All rights reserved.