Как сделать комбинированные жесты?

Я хочу спросить кое-что интересное. Я хочу, чтобы мое приложение могло действовать, когда происходят пользовательские комбинированные жесты. Например: вызовите действие (/метод), когда пользователь проводит пальцем влево, вверх, влево, не оставляя палец на экране. Как я могу сделать этот пользовательский жест?

и второй вопрос: могу ли я провести пальцем вверх влево (например, «/ » в этом направлении)? Как сделать этот жест?

кто-нибудь может мне помочь? пожалуйста! Спасибо


person Steve Lai    schedule 14.08.2013    source источник


Ответы (1)


Что ж, концептуально вам нужно создать подкласс UIGestureRecognizer, выполнить некоторое отслеживание положения и использовать тот факт, что после импорта UIGestureRecognizerSubclass.h свойство состояния жестов становится доступным для чтения/записи, чтобы перемещать все шестеренки вокруг себя. В качестве примера я включу базовый прототип диагонального жеста, который я пытался построить давным-давно. (Ему нужно проработать несколько изгибов, но в целом он работает.)

.H

#import <UIKit/UIKit.h>
#import <UIKit/UIGestureRecognizerSubclass.h>

@interface MMDiagnoalSwipeGestureRecognizer : UIGestureRecognizer
@property (nonatomic, readwrite) BOOL shouldReverseYDelta;
@property (nonatomic, readwrite) CGFloat tolerance;
@property (nonatomic, readonly) CGFloat angleOfSwipe;
@end

.M

#import "MMDiagnoalSwipeGestureRecognizer.h"
@interface MMDiagnoalSwipeGestureRecognizer ()
@property (nonatomic, readwrite) CGPoint startingPoint;
@end

@implementation MMDiagnoalSwipeGestureRecognizer


- (id)initWithTarget:(id)target action:(SEL)action {
    self = [super initWithTarget:target action:action];
    if (self) {
        _shouldReverseYDelta = NO;
        _tolerance = 30.0f;
    }
    return self;
}

- (CGFloat)angleOfGestureFromPoint:(CGPoint)start toEndPoint:(CGPoint)end {
    CGFloat deltaY = (_shouldReverseYDelta) ? end.y - start.y : start.y - end.y;
    CGFloat deltaX = end.x - start.x;

    _angleOfSwipe = atan2f(deltaY, deltaX) * 180.0f / M_PI;

    return _angleOfSwipe;
}

- (CGFloat)diagonalDistanceFromPoint:(CGPoint)start toEndPoint:(CGPoint)end {
    CGFloat deltaX = fabsf(start.x - end.x);
    CGFloat deltaY = fabsf(start.y - end.y);

    CGFloat hypotenuse = powf(deltaX, 2.0f) + powf(deltaY, 2.0f);

    return sqrtf(hypotenuse);
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (touches.count > 1) {
        if (self.state == UIGestureRecognizerStatePossible) {
            self.state = UIGestureRecognizerStateFailed;
        }
    }else{
        [touches enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
            UITouch *touch = (UITouch *)obj;
            _startingPoint = [touch locationInView:self.view];
        }];
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    [touches enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
        UITouch *touch = (UITouch *)obj;
        CGPoint endPoint = [touch locationInView:self.view];
        CGFloat angle = [self angleOfGestureFromPoint:_startingPoint toEndPoint:endPoint];

        if (self.state == UIGestureRecognizerStatePossible) {
            if ([self angleIsWithinDiagonalTolerance:angle] == YES) {
                if ([self diagonalDistanceFromPoint:_startingPoint toEndPoint:endPoint] >= 20.0f) {
                    self.state = UIGestureRecognizerStateRecognized;
                }
            }else{
                self.state = UIGestureRecognizerStateFailed;
            }
        }
    }];
}

- (BOOL)angleIsWithinDiagonalTolerance:(CGFloat)angle
{
//    NSLog(@"%s",__PRETTY_FUNCTION__);
    NSAssert1(_tolerance < 45.0f, @"DiagonalSwipeGestureRecognizer Error: tolerance property must be set to a value less than 45.0f. Otherwise, the gesture will be detected at any angle. If you don't care and want the swipe to be recognized at any angle, remove the NSAssert call from - %s.", __PRETTY_FUNCTION__);
//    NSAssert(_tolerance < 45.0f, @"DiagonalSwipeGestureRecognizer Error: tolerance property must be set to a value less than 45.0f. Otherwise, the gesture will be detected at any angle. If you don't care and want the swipe to be recognized at any angle, remove the NSAssert call from -[MMDiagnoalGestureRecognizer angleIsWithinDiagonalTolerance:].");

    if (angle >= 45.0f - _tolerance && angle <= 45.0f + _tolerance) {
        return YES;
    }else if (angle <= - (45.0f - _tolerance) && angle >= - (45.0f + _tolerance)) {
        return YES;
    }else if (angle >= 135.0f - _tolerance && angle <= 135.0f + _tolerance) {
        return YES;
    }else if (angle <= - (135.0f - _tolerance) && angle >= - (135.0f + _tolerance)) {
        return YES;
    }else{
        return NO;
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [self touchesEnded:touches withEvent:event];
    self.state = UIGestureRecognizerStateChanged;
}

- (void)reset {
    //don't call, will be called automatically.
}



@end
person Mick MacCallum    schedule 14.08.2013