Combining a UILongPressGestureRecognizer with a UIPanGestureRecognizer

Viewed 11475

I d'like to combine a UILongPressGestureRecognizer with a UIPanGestureRecognizer.

The UIPanGestureRecognizer should start with a long press. Is there a simple way to do this? or do I really have to write my own gesture recognizer?

I wan't something like on the home screen. You press on an icon and after some time the icons start wobbling. Afterwards without releasing my finger from the screen I can start dragging the icon under my finger around.

7 Answers

For combinate more gesture :

  1. Create a local variable var shouldAllowSecondGesture : Bool = false
  2. Create the two recognizer

let longPressRec = UILongPressGestureRecognizer(target: self, action: #selector(self.startDrag(sender:))) cell.addGestureRecognizer(longPressRec) let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(sender:))) cell.isUserInteractionEnabled = true cell.addGestureRecognizer(panGestureRecognizer)

  1. Extension your VC and implement GestureRecognizerDelegate for implemented this method.

    extension YourViewController : UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return true
        }
    
    
    
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
             // We only allow the (drag) gesture to continue if it is within a long press
             if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) {
                 return false
             }
             return true
        }
    
    
    @objc func startDrag(sender:UIPanGestureRecognizer) {
    
        if(sender.state == .began) {
                // handle the long press
            }
        else if(sender.state == .changed){
                shouldAllowPan = true
    
            }
            else if (sender.state == .ended) {
                shouldAllowPan = false
            }
        }
    

I solved this issue by implementing the desired functionality of the "action: Selector?" func of the UIPanGestureRecognizer within the "action: Selector?" func for the UILongPressGestureRecognizer.

As 'UILongPressGestureRecognizer' has no member 'translation', I calculated the translation by saving the position of the original touch and them extracting it from the actual touch position.


// in target class
var initialTouchX : CGFloat
var initialTouchX : CGFloat


// in the @objc func for the UILongPressGestureRecognizer
if sender.state == .began {
   initialTouchX = sender.location(in: sender.view).x
   initialTouchY = sender.location(in: sender.view).y
}

let translation = CGVector(dx: sender.location(in: sender.view).x - initialTouchX, dy: sender.location(in: sender.view).y - initialTouchY)


Related