Как определить, что несколько UIGestureRecognizer заканчиваются? - PullRequest
0 голосов
/ 01 марта 2020

На мой взгляд, у меня есть несколько распознавателей жестов (UIPanGestureRecognizer, UIPinchGestureRecognizer и UIRotationGestureRecognizer), и я позволил им обнаруживать касания одновременно:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
                       shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    if gestureRecognizer.view != otherGestureRecognizer.view {
       return false
    }

    return true
}

Проблема с этим подходом заключается в том, что я больше не могу обнаружить когда все 3 жеста заканчиваются. Я не могу использовать

    if gesture.state == .ended || gesture.state == .cancelled {
    }

, потому что это действительно только для распознавателя жестов, а не для всех 3.

Есть идеи, есть ли API для обнаружения, когда все активные распознаватели заканчиваются?

Спасибо


Решение

Это работает, но очень уродливо: в основном я слежу за окончанием всех трех распознавателей жестов и не могу обнаружить завершается несколько раз, так как обратный вызов распознавателя может быть вызван в любом порядке:

class SCCanvasViewController: UIViewController {
    var gesturesAlreadyEnded = false

    lazy var panGestureRecognizer: UIPanGestureRecognizer = {
        let gr = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
        gr.delegate = self
        return gr
    }()

    lazy var pinchGestureRecognizer: UIPinchGestureRecognizer = {
        let gr = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
        gr.delegate = self
        return gr
    }()

    lazy var rotateGestureRecognizer: UIRotationGestureRecognizer = {
        let gr = UIRotationGestureRecognizer(target: self, action: #selector(handleRotation(_:)))
        gr.delegate = self
        return gr
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addGestureRecognizer(panGestureRecognizer)
        view.addGestureRecognizer(pinchGestureRecognizer)
        view.addGestureRecognizer(rotateGestureRecognizer)
    }

    func isGestureEnded(gesture: UIGestureRecognizer) -> Bool {
        return gesture.state == .ended || gesture.state == .cancelled || gesture.state == .failed
    }

    func allGesturesEnded() -> Bool {
        let panEnded = isGestureEnded(gesture: panGestureRecognizer)
        let pinchEnded = isGestureEnded(gesture: pinchGestureRecognizer)
        let rotationEnded = isGestureEnded(gesture: rotateGestureRecognizer)
        return panEnded && pinchEnded && rotationEnded
    }

    @objc func handlePan(_ gesture: UIPanGestureRecognizer) {
        if gesture.state == .began {
            gesturesAlreadyEnded = false
        }

        if !gesturesAlreadyEnded && isGestureEnded(gesture: gesture) {
            canvasView.showHorizontalSnapIndicators(areVisible: false)
            canvasView.showVerticalSnapIndicators(areVisible: false)
            if (allGesturesEnded()) {
                gesturesAlreadyEnded = true
                print("Can create transformation command")
            }
            return
        }
    }

    @objc func handlePinch(_ gesture: UIPinchGestureRecognizer) {
        if gesture.state == .began {
            gesturesAlreadyEnded = false
        }

        if !gesturesAlreadyEnded && isGestureEnded(gesture: gesture) {
            if (allGesturesEnded()) {
                gesturesAlreadyEnded = true
                print("Can create transformation command")
            }
            return
        }
    }

    @objc func handleRotation(_ gesture: UIRotationGestureRecognizer) {
        if gesture.state == .began {
            gesturesAlreadyEnded = false
        }

        if !gesturesAlreadyEnded && isGestureEnded(gesture: gesture) {
            if (allGesturesEnded()) {
                gesturesAlreadyEnded = true
                print("Can create transformation command")
            }
            return
        }
    }
}

extension SCCanvasViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
                           shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        if gestureRecognizer.view != otherGestureRecognizer.view {
           return false
        }

        return true
    }
}

1 Ответ

1 голос
/ 01 марта 2020

Настройте его для получения уведомлений с несколькими касаниями, затем изучите набор касаний, на которые повлияло событие.

class TouchableView: UIView {
   var touchViews = [UITouch:TouchSpotView]() 

   override init(frame: CGRect) {
      super.init(frame: frame)
      isMultipleTouchEnabled = true
   }

   required init?(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
      isMultipleTouchEnabled = true
   }

   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
      for touch in touches {
         createViewForTouch(touch: touch)
      }
   }

   override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
      for touch in touches {
         let view = viewForTouch(touch: touch) 
         // Move the view to the new location.
         let newLocation = touch.location(in: self)
         view?.center = newLocation
      }
   }

   override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
      for touch in touches {
         removeViewForTouch(touch: touch)
      }
   }

   override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
      for touch in touches {
         removeViewForTouch(touch: touch)
      }
   }

   // Other methods. . . 
}
...