Detecting Pan Gesture End
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?
Solution 1:
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:
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:
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:
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:
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.