I've written a UIGestureRecognizer
subclass for that purpose once. It only tracks the vertical translation. Maybe that helps you. You can use it as any other gesture recognizer, just set the threshold and track the translation in the it's target's action method.
VerticalPanGestureRecognizer.h
#import <UIKit/UIKit.h>
#import <UIKit/UIGestureRecognizerSubclass.h>
@interface VerticalPanGestureRecognizer : UIGestureRecognizer
@property (assign, nonatomic)float translation;
@property (assign, nonatomic)float offsetThreshold;
@end
VerticalPanGestureRecognizer.m
#import "VerticalPanGestureRecognizer.h"
@interface VerticalPanGestureRecognizer ()
{
CGPoint _startPoint;
}
@end
@implementation VerticalPanGestureRecognizer
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] > 1) {
self.state = UIGestureRecognizerStateFailed;
}
else
{
_startPoint = [[touches anyObject] locationInView:self.view];
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (self.state == UIGestureRecognizerStateFailed || self.state == UIGestureRecognizerStateCancelled) {
return;
}
CGPoint currentLocation = [[touches anyObject] locationInView:self.view];
CGPoint translation;
translation.x = currentLocation.x - _startPoint.x;
translation.y = currentLocation.y - _startPoint.y;
if (self.state == UIGestureRecognizerStatePossible)
{
//if the x-translation is above our threshold the gesture fails
if (fabsf(translation.x) > self.offsetThreshold)
self.state = UIGestureRecognizerStateFailed;
//if the y-translation has reached the threshold the gesture is recognized and the we start sending action methods
else if (fabsf(translation.y) > self.offsetThreshold)
self.state = UIGestureRecognizerStateBegan;
return;
}
//if we reached this point the gesture was succesfully recognized so we now enter changed state
self.state = UIGestureRecognizerStateChanged;
//we are just insterested in the vertical translation
self.translation = translation.y;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//if at this point the state is still 'possible' the threshold wasn't reached at all so we fail
if (self.state == UIGestureRecognizerStatePossible)
{
self.state = UIGestureRecognizerStateFailed;
}
else
{
CGPoint currentLocation = [[touches anyObject] locationInView:self.view];
CGPoint translation;
translation.x = _startPoint.x - currentLocation.x;
translation.y = _startPoint.y - currentLocation.y;
self.translation = translation.y;
self.state = UIGestureRecognizerStateEnded;
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
self.state = UIGestureRecognizerStateCancelled;
}
- (void)reset
{
[super reset];
_startPoint = CGPointZero;
}
@end