How to recognize swipe in all 4 directions
Unfortunately you cannot use direction
property for listening the recognizer; it only gives you the detected directions by the recognizer. I have used two different UISwipeGestureRecognizer
s for that purpose, see my answer here: https://stackoverflow.com/a/16810160/936957
I actually ran into this exact problem before. What I ended up doing was creating a UIView subclass, overriding touchesMoved:
and doing some math to calculate the direction.
Here's the general idea:
#import "OmnidirectionalControl.h"
typedef NS_ENUM(NSInteger, direction) {
Down = 0, DownRight = 1,
Right = 2, UpRight = 3,
Up = 4, UpLeft = 5,
Left = 6, DownLeft = 7
};
@interface OmnidirectionalControl ()
@property (nonatomic) CGPoint startTouch;
@property (nonatomic) CGPoint endTouch;
@end
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
self.startTouch = [[touches allObjects][0] locationInView:self];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
self.lastTouch = [[[touches allObjects] lastObject] locationInView:self];
NSLog(@"Direction: %d", [self calculateDirectionFromTouches]);
}
-(direction)calculateDirectionFromTouches {
NSInteger xDisplacement = self.lastTouch.x-self.startTouch.x;
NSInteger yDisplacement = self.lastTouch.y-self.startTouch.y;
float angle = atan2(xDisplacement, yDisplacement);
int octant = (int)(round(8 * angle / (2 * M_PI) + 8)) % 8;
return (direction) octant;
}
For simplicity's sake in touchesMoved:
, I only log the direction, but you can do what you want with that information (e.g. pass it to a delegate, post a notification with it, etc.). In touchesMoved
you'll also need some method to recognize if the swipe is finished or not, but that's not quite relevant to the question so I'll leave that to you. The math in calculateDirectionFromTouches
is explained here.
You set the direction like this
UISwipeGestureRecognizer *Swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipeRecognizer:)];
Swipe.direction = (UISwipeGestureRecognizerDirectionLeft |
UISwipeGestureRecognizerDirectionRight |
UISwipeGestureRecognizerDirectionDown |
UISwipeGestureRecognizerDirectionUp);
That's what the direction will be when you get the callback, so it is normal that all your tests fails. If you had
- (void) SwipeRecognizer:(UISwipeGestureRecognizer *)sender {
if ( sender.direction | UISwipeGestureRecognizerDirectionLeft )
NSLog(@" *** SWIPE LEFT ***");
if ( sender.direction | UISwipeGestureRecognizerDirectionRight )
NSLog(@" *** SWIPE RIGHT ***");
if ( sender.direction | UISwipeGestureRecognizerDirectionDown )
NSLog(@" *** SWIPE DOWN ***");
if ( sender.direction | UISwipeGestureRecognizerDirectionUp )
NSLog(@" *** SWIPE UP ***");
}
The tests would succeed (but the would all succeed so you wouldn't get any information out of them). If you want to distinguish between swipes in different directions you will need separate gesture recognizers.
EDIT
As pointed out in the comments, see this answer. Apparently even this doesn't work. You should create swipe with only one direction to make your life easier.