ios - 如何做出组合手势?

标签 ios gestures

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

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

谁能帮帮我?请!谢谢

最佳答案

好吧,从概念上讲,您需要子类化 UIGestureRecognizer,进行一些位置跟踪,并利用在导入 UIGestureRecognizerSubclass.h 之后手势状态属性变为读/写以移动所有齿轮的事实你自己。作为示例,我将包含一个我很久以前尝试构建的对角线手势的基本原型(prototype)。 (它需要解决一些问题,但总的来说,它是有效的。)

.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

关于ios - 如何做出组合手势?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18231396/

相关文章:

c# - WPF 4 触摸事件获取捏合手势的中心

iphone - iOS - 如何显示 iOS 应用程序的手势提示?

iOS Instagram 标签文本布局?它是如何完成的?

ios - 如何创建展开和折叠表格 View ?

ios - 当弹跳设置为 NO 时,嵌套的 UIScrollView 不会弹跳并且不会检测慢速滑动手势

ios - Accordion 风格菜单 ios

windows - 在 delphi XE7 中找不到 vcl 组件的交互式手势事件,如 igiZoom、igiPan 或 igiRotate

javascript - 桌面 webapp 中的多点触控手势

ios - 一个项目中无法进行日志记录(NSLogs 不起作用)