SwiftUI:多点触控手势/多个手势

Mat*_*art 8 multi-touch gesture swiftui

SwiftUI 中是否可以同时跟踪多个手势?我希望我的一个主视图能够同时跟踪多个手指拖动。

ZStack {
    Color.black
      .edgesIgnoringSafeArea(.all)
      .gesture(DragGesture(minimumDistance: 0)
               .onChanged { (value) in
                 //some logic
               }.onEnded { (value) in
                  //more logic         
               })
       //other code
}
Run Code Online (Sandbox Code Playgroud)

我有这个代码,但是我一次只能处理一个拖动手势。如果一个手指在拖动,然后我尝试添加另一个手指,第一个停止。

我试图实现多个手指同时在屏幕上的效果。每个手指同时拖动一个圆圈(一个圆圈跟随每个手指)。

我在 Apple 的文档中看到了同步手势,但这是指一个手势触发多个块。

小智 3

使用 UIViewRepresentable 的解决方案(如何在 SwiftUI 中检测点击手势位置? )可以工作。虽然它不是纯粹的 swiftUI 解决方案(我一直在寻找纯粹的 swiftUI 解决方案,但找不到一个,并且有兴趣看到一个)。我已将代码更新为以下代码,您需要更改 numberOfTouchPoints = 5。然后使用回调将值放入视图中。

struct TapView: UIViewRepresentable {
    var tappedCallback: (() -> Void)

    func makeUIView(context: UIViewRepresentableContext<TapView>) -> TapView.UIViewType {
        let v = UIView(frame: .zero)
        let gesture = NFingerGestureRecognizer(target: context.coordinator,
                                                       action: #selector(Coordinator.tapped))
        v.addGestureRecognizer(gesture)
        return v
    }

    class Coordinator: NSObject {
        var tappedCallback: (() -> Void)

        init(tappedCallback: @escaping (() -> Void)) {
            self.tappedCallback = tappedCallback
        }

        @objc func tapped(gesture:NFingerGestureRecognizer) {
            for i in 0..<gesture.numberOfTouches{
                print(gesture.location(ofTouch: i, in: gesture. view))
            }
            self.tappedCallback()
        }
    }

    func makeCoordinator() -> TapView.Coordinator {
        return Coordinator(tappedCallback:self.tappedCallback)
    }

    func updateUIView(_ uiView: UIView,
                      context: UIViewRepresentableContext<TapView>) {
    }
}

class NFingerGestureRecognizer: UIGestureRecognizer {
    var numberOfTouchPoints: Int = 2
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        if self.state == .possible {
            if (self.numberOfTouches == numberOfTouchPoints){ // we have a two finger interaction starting
                self.state = .began
                print("two finger drag - Start")
            }
        } else {        // check to see if there are more touchs
            if (self.numberOfTouches > numberOfTouchPoints){ // we have a two finger interaction starting
                self.state = .failed
                print("two finger drag - failed")
            }
        }
        //printInternalTouches()
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        if (self.state != .possible){
            self.state = .changed        // we are looking for two finger interaction
            //printInternalTouches()
            print("changed")
        }
    }
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
        if numberOfTouches == 2 {
            state = .ended
        }
        else {
            state = .failed
        }
        //printInternalTouches()
        print("ended")
    }
    
    private func printInternalTouches(){
        // now print the internal touchUI elements - should be the better solution
        print("Internal Locations")
        for i in 0..<self.numberOfTouches{
            print(self.location(ofTouch: i, in: self.view))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)