UIKit 触控板:在单击 + 拖动时,检测额外的非触摸式拖动

Chr*_*itt 7 uikit ipad ios swift swiftui

立即目标:在触控板单击 + 拖动手势期间,检测附加(无单击)触控板拖动/平移手势并做出反应。

\n

问题:只要第一次触控板单击+拖动正在进行,UIKit 似乎就会忽略触控板上额外的、无单击的两指平移。

\n

大图 UX:\xe2\x80\x9cclick + 拖动\xe2\x80\x9d 和 \xe2\x80\x9cclick + 拖动 + 另一个平移\xe2\x80\x9d 应该有不同的行为。

\n

示例:所需的行为类似于 Figma:当抓取组件\xe2\x80\x99s 名称时,另外两个手指的平移手势将导致背景(而不是组件)四处移动。

\n

现在:

\n
    \n
  • 只需在触控板上单击并拖动即可:触发触摸 = 1 的手势
  • \n
  • 只需在触控板上平移/拖动(无点击):触发触摸 = 0 的手势
  • \n
  • 在单击 + 拖动期间,添加另一个平移/拖动:与触摸 = 1 触发相同的手势
  • \n
\n

我\xe2\x80\x99VE尝试过:

\n
    \n
  • 查看各种手势识别器的触摸和位置
  • \n
  • 查看UIGestureRecognizerDelegate\xe2\x80\x99s 委托方法,例如gestureRecognizer(_:shouldReceive:)
  • \n
  • minTouches = 1在一个触控板上 UIKit 手势识别器(即单击+拖动)和maxTouches = 0另一个(即无单击拖动)
  • \n
  • (此处未共享代码):一个可注入的 UIKit 包装器,位于整个视图上,并且还侦听触控板手势(与上面的结果相同)
  • \n
\n

代码:

\n
import SwiftUI\n\nstruct StackOverflowUIKitView: View {\n    var nodeView: some View {\n        Rectangle()\n            .fill(.red.opacity(0.9))\n            .frame(width: 100, height: 100)\n            .overlay(TrackpadUIKitGesture(name: "Node"))\n            .position(x: 500, y: 400)\n    }\n\n    var body: some View {\n        ZStack { nodeView }\n            .border(.purple, width: 18)\n            .background(TrackpadUIKitGesture(name: "Graph"))\n    }\n}\n\nstruct TrackpadUIKitGesture: UIViewControllerRepresentable {\n\n    let name: String\n\n    func makeUIViewController(context: Context) -> UIViewController {\n        let vc = UIViewController()\n        let delegate = context.coordinator\n\n        let trackpadPan = UIPanGestureRecognizer(\n            target: delegate,\n            action: #selector(delegate.trackpadPanInView))\n        trackpadPan.allowedScrollTypesMask = [.continuous, .discrete]\n        trackpadPan.allowedTouchTypes = [NSNumber(value: UITouch.TouchType.indirectPointer.rawValue)]\n        trackpadPan.delegate = delegate\n        vc.view.addGestureRecognizer(trackpadPan)\n\n        return vc\n    }\n\n    func updateUIViewController(_ uiViewController: UIViewController,\n                                context: Context) { }\n\n    func makeCoordinator() -> TrackpadDelegate {\n        TrackpadDelegate(name: name)\n    }\n}\n\nclass TrackpadDelegate: NSObject, UIGestureRecognizerDelegate {\n\n    let name: String\n\n    init(name: String) {\n        self.name = name\n    }\n\n    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,\n                           shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {\n        true\n    }\n\n    @objc func trackpadPanInView(_ gestureRecognizer: UIPanGestureRecognizer) {\n        guard let view = gestureRecognizer.view else {\n            fatalError("\\(name) error: no view.")\n        }\n\n        let touches = gestureRecognizer.numberOfTouches\n        let state = gestureRecognizer.state\n\n        let translation = gestureRecognizer.translation(in: view).toCGSize\n        let location = gestureRecognizer.location(in: view)\n\n        log("\\(name): touches: \\(touches)")\n        log("\\(name): state: \\(state)")\n        log("\\(name): translation: \\(translation)")\n        log("\\(name): location: \\(location)")\n\n        if touches > 1 {\n            let touch0 = gestureRecognizer.location(ofTouch: 0, in: view)\n            log("\\(name): touch0: \\(touch0)")\n        }\n    }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n