1

我想问一些有趣的事情。我希望我的应用程序可以在自定义组合手势发生时采取行动。例如:当用户向左、上、左滑动而不手指离开屏幕时调用一个动作(/方法)。我怎样才能做出这个自定义手势?

第二个问题是我可以向左上滑动(比如“/”这个方向)吗?这个手势怎么做?

任何人都可以帮助我吗?请!谢谢

4

1 回答 1

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
于 2013-08-14T12:17:06.537 回答