Detecting Pan Gesture End

Objective CTouchUigesturerecognizer

Objective C Problem Overview


I've got a view and I applied a UIPanGestureRecogniser to this view:

UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAnim:)];
[sliderView addGestureRecognizer:panGesture];
[panGesture release];

I can detect and process the gesture just fine. However, I wish to initiate another method once the gesture has ended.

I know there are two methods that allow this kind of detection. touchesEnded and touchesCancelled however, I've found that touchesCancelled gets called as soon as the touch becomes a gesture i.e. I move my finger enough to warrant a gesture call and touchesEnded rarely, if ever, gets called.

I want to be able to pan left / right and then initiate another function call upon gesture ending. How do I do this?

Objective C Solutions


Solution 1 - Objective C

Pan gesture end event can be detected by checking its state with UIGestureRecognizerStateEnded.

Check with the below code .

-(void) panAnim:(UIPanGestureRecognizer*) gestureRecognizer
{
   if(gestureRecognizer.state == UIGestureRecognizerStateEnded)
   {
      //All fingers are lifted.
   }
}

From Apple documentation

> A panning gesture is continuous. It > begins (UIGestureRecognizerStateBegan) > when the minimum number of fingers > allowed (minimumNumberOfTouches) has > moved enough to be considered a pan. > It changes > (UIGestureRecognizerStateChanged) when > a finger moves while at least the > minimum number of fingers are pressed > down. It ends > (UIGestureRecognizerStateEnded) when > all fingers are lifted.

Read more about UIPanGestureRecognizer

Solution 2 - Objective C

Pan gesture end event can be detected by checking the it's state with UIGestureRecognizerStateEnded or UIGestureRecognizerStateCancelled or UIGestureRecognizerStateFailed

Check with the below code .

   -(void) panGesture:(UIPanGestureRecognizer*) gestureRecognizer
    {
     if(gestureRecognizer.state == UIGestureRecognizerStateEnded || gestureRecognizer.state == UIGestureRecognizerStateFailed || gestureRecognizer.state == UIGestureRecognizerStateCancelled)
             {
                //code what you want.
             }
     }

Solution 3 - Objective C

Above answers are all correct, this is just an updated one for Swift.

Swift 3:

func panGesture(recognizer: UIPanGestureRecognizer) {
    if recognizer.state == .ended {
        // Do what you want
    }
}

Solution 4 - Objective C

In Swift 4, use UIGestureRecognizerState.ended.

e.g.

if (gestureRecognizer.state == UIGestureRecognizerState.ended) {
        
        //Move label back to original position (function invoked when gesture stops)
        UIView.animate(withDuration: 0.4) {
            self.swipeLabel.center = CGPoint(x: self.view.bounds.width / 2, y: self.view.bounds.height / 2)
        }
    }

Below is all the code you need in a view controller to animate a UILabel with gesture, including when the gesture ends.

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var swipeLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    
    //Create gesture
    let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(moveLabelBasedOn(gestureRecognizer:)))
    
    //Assign gesture to UILabel
    swipeLabel.addGestureRecognizer(gestureRecognizer)

}

//Animate Label in Resopnse to Gesture
@objc func moveLabelBasedOn(gestureRecognizer: UIPanGestureRecognizer) {
    
    let changeInPosition = gestureRecognizer.translation(in: view)
    
    //Move label in response to gesture
    swipeLabel.center = CGPoint(x: view.bounds.width / 2 + changeInPosition.x, y: view.bounds.height / 2 + changeInPosition.y)
    
    //Check if gesture ended
    if (gestureRecognizer.state == UIGestureRecognizerState.ended) {
        
        //Move label back to original position (function invoked when gesture stops)
        UIView.animate(withDuration: 0.4) {
            self.swipeLabel.center = CGPoint(x: self.view.bounds.width / 2, y: self.view.bounds.height / 2)
        }
    }
}

}

Hope this helps.

Solution 5 - Objective C

This would not work for a two (or more) finger pan. In this case with numberOfMinimumTouches = 2, the pan would start and you can scroll/pan around, but if you lift one finger, the pan will still continue (move to where the one finger is instead of between the two fingers), since the State.ended is only when ALL fingers are lifted. To stop based on the numberOfMinimumTouches value, a different approach needs to be implemented.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDan HanlyView Question on Stackoverflow
Solution 1 - Objective CJhaliya - Praveen SharmaView Answer on Stackoverflow
Solution 2 - Objective CWaseem ShahView Answer on Stackoverflow
Solution 3 - Objective CRay TsoView Answer on Stackoverflow
Solution 4 - Objective CDouglas PutnamView Answer on Stackoverflow
Solution 5 - Objective Cuser3577199View Answer on Stackoverflow