I've made UIPanGestureRecognizer only detect mostly vertical pans, how do I make it only detect REALLY vertical pans?

谁说胖子不能爱 提交于 2019-12-04 20:15:28
Rob

You can use atan2f given x and y values to calculate the angle from vertical. For example, to start the gesture if the angle is less than 4 degrees from vertical, you can do something like this:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gesture {
    CGPoint translation = [gesture translationInView:gesture.view];
    if (translation.x != 0 || translation.y != 0) {
        CGFloat angle = atan2f(fabs(translation.x), fabs(translation.y));
        return angle < (4.0 * M_PI / 180.0); // four degrees, but in radians
    }
    return FALSE;
}

Detecting pure vertical gestures, I assume that translation.x == 0 then.

You should as well, check the correct answer from the post you referenced. Where he compares the previous location with the current one. You can create the sensibility. You can check my project, for example to see that, where I use this sensibility to define, when an action is valid (less or equal than the sensibility) or invalid (bigger than the sensibility). Check the MOVEMENT_SENSIBILITY inside the RPSliderViewController.m.

Tobi

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!