闻道丶iOS(大杂烩)timeiOS

【iOS】API之UIGestureRecognizer及自定义

2016-11-10  本文已影响2323人  HoyaWhite

在unity开发中,触屏手势在我看来是以手指ID号(手指的身份)以及手指状态为标准界定判断手势的类型的;一些插件感觉和iOS中苹果封装的差不多,因此就UIGestureRecognizer这个类关于API使用进行一下初步探索。。。


一、UIGestureRecognizer

  1. 给手势添加多个Target; 触发后执行顺序按照添加的顺序执行


  2. 获取手指相对于某一个view位置




    第二个方法中touchIndex是手指的序号(比如手势是两个手指触发,手指接触屏幕肯定有先后,第一个接触的系统内部自动给其标为第0个,第二个手指给其标记为第1个)

  3. 不太明白的东西

  4. UIGestureRecognizer.state介绍

  1. UIGestureRecognizer.delegate介绍

二、UIGestureRecognizer子类

UIGestureRecognizer子类有:

UITapGestureRecognizer(轻击)
UILongPressGestureRecognizer(长按)
​UISwipeGestureRecognizer(轻扫)
UIPanGestureRecognizer(拖动)
UIPinchGestureRecognizer(捏合)
UIRotationGestureRecognizer(旋转)
UIScreenEdgePanGestureRecognizer(屏幕边缘手势继承于pan手势)

轻击UITapGestureRecognizer
长按UILongPressGestureRecognizer
轻扫​UISwipeGestureRecognizer
拖动UIPanGestureRecognizer
//拖动触发后调用
- (void)panGes:(UIPanGestureRecognizer *)ges{
    if (ges.state == UIGestureRecognizerStateChanged) {
        //注意这个方法获取到的偏移量是相对于开始识别到时候手指的位置并不会实时更新需要再调用setTranslation: inView:
        CGPoint p = [ges translationInView:self.redView];
        [ges setTranslation:CGPointZero inView:self.redView];
        self.redView.frame = CGRectMake(self.redView.frame.origin.x + p.x, self.redView.frame.origin.y + p.y, self.redView.frame.size.width, self.redView.frame.size.height);
    }
}
捏合UIPinchGestureRecognizer
//捏合触发后调用
- (void)pinchAction:(UIPinchGestureRecognizer *)ges{
    if (ges.state == UIGestureRecognizerStateChanged) {
        self.redView.transform = CGAffineTransformMakeScale(ges.scale, ges.scale);
    }
    if(ges.state == UIGestureRecognizerStateEnded)
    {
        [UIView animateWithDuration:0.5 animations:^{
            self.redView.transform = CGAffineTransformIdentity;//取消一切形变
        }];
    }
}
旋转UIRotationGestureRecognizer
//旋转触发后调用
- (void)rotaAction:(UIRotationGestureRecognizer *)ges{
    if (ges.state==UIGestureRecognizerStateChanged)
    {
        self.redView.transform=CGAffineTransformMakeRotation(ges.rotation);
    }
    if(ges.state==UIGestureRecognizerStateEnded)
    {
        [UIView animateWithDuration:1 animations:^{
            self.redView.transform=CGAffineTransformIdentity;//取消形变
        }];
    }
}
屏幕边缘手势UIScreenEdgePanGestureRecognizer

三、自定义手势

好吧,我触发不了系统屏幕边缘手势我自己写一个行了吧。。。。自定义手势需要注意几点:

WPGesture.h

#import <UIKit/UIKit.h>

@interface WPGesture : UIGestureRecognizer
//需要几根手指
@property(nonatomic, assign)NSUInteger wpNumberOfTouchesRequired;//默认1
//需要几次点击
@property(nonatomic, assign)NSUInteger wpNumberOfTapsRequired;//默认0
//哪一边
@property (readwrite, nonatomic, assign) UIRectEdge wpEdges;//默认UIRectEdgeAll

@end

WPGesture.m

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

@interface WPGesture()
@property(nonatomic, assign)BOOL isCorrected;

@end
@implementation WPGesture
//在began里面识别手势是否正确: 几根手指 几次点击 哪一边  此方法左右:作为手势识别器
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    NSArray *allTouches = [touches allObjects];
    //0.判断手指的tapCount  是否在move里面给出移动初始点
    for (UITouch * tou in allTouches) {
        if(tou.tapCount != (self.wpNumberOfTapsRequired + 1)){
            //不符合的话直接return 不再继续判断
            return;
        }
    }

    //1.判断手指个数是否符合
    if(allTouches.count != self.wpNumberOfTouchesRequired){
        //忽略不正确手指 防止干扰到识别
        for (UITouch * tou in allTouches) {
            [self ignoreTouch:tou forEvent:event];
        }
        return;
    }
    
    //2.手指个数满足情况下 判断手指位置是否满足条件
    //用临时变量topM等接收 防止屏幕旋转出现
    CGFloat topM = self.view.bounds.size.height *0.25;//满足点要小于top
    CGFloat butM = self.view.bounds.size.height *0.75;//满足点要大于but
    CGFloat lefM = self.view.bounds.size.width *0.25;//满足点要小于lef
    CGFloat rigM = self.view.bounds.size.width *0.75;//满足点要大于rig
    if (topM >= 100) {
        topM = 100;
        butM = self.view.bounds.size.height - 100;
    }
    if (lefM >= 100) {
        lefM = 100;
        rigM = self.view.bounds.size.width - 100;
    }
    // 判断手指位置是否满足条件
    for (UITouch * tou in allTouches) {
        if (!self.view) {
            return;
        }//貌似能触发began就肯定有view
        CGPoint touchP = [tou locationInView:self.view];//手指位置
        if (self.wpEdges == UIRectEdgeNone) {
            return;//UIRectEdgeNone什么也不做
        }
        if (self.wpEdges == UIRectEdgeTop) {
            if (touchP.y > topM) {
                [self ignoreTouch:tou forEvent:event];
                return;
            }
        }
        if (self.wpEdges == UIRectEdgeBottom) {
            if (touchP.y < butM) {
                [self ignoreTouch:tou forEvent:event];
                return;
            }
        }
        if (self.wpEdges == UIRectEdgeLeft) {
            if (touchP.x > lefM) {
                [self ignoreTouch:tou forEvent:event];
                return;
            }
        }
        if (self.wpEdges == UIRectEdgeRight) {
            if (touchP.x < rigM) {
                [self ignoreTouch:tou forEvent:event];
                return;
            }
        }
        if (self.wpEdges == UIRectEdgeAll) {
            if (touchP.y > topM && touchP.y < butM && touchP.x > lefM && touchP.x < rigM) {
                [self ignoreTouch:tou forEvent:event];
                return;
            }
        }
    }
    self.isCorrected = YES;//识别正确,当前状态UIGestureRecognizerStatePossible
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [super touchesMoved:touches withEvent:event];
    if (!self.isCorrected) {
        //不满足began的情况 直接返回
        return;
    }
    //识别正确 移动既是began
    self.state = UIGestureRecognizerStateBegan;//自动内部会自动改变状态为move 
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [super touchesEnded:touches withEvent:event];
    if(self.isCorrected){
        self.state = UIGestureRecognizerStateEnded;
        self.state = UIGestureRecognizerStateRecognized;
        [self reset];
    }
}

#pragma mark - 重写方法
- (void)reset{
    [super reset];
    self.isCorrected = NO;
}

//没有end状态 又识别到其他手势的时候  多了手指出来
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer{
    BOOL res = [super canPreventGestureRecognizer:preventedGestureRecognizer];
    self.state = UIGestureRecognizerStateCancelled;
    [self reset];
    return res;
}

//第一次识别 touchBegan之后调用
- (BOOL)shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    BOOL res = [super shouldRequireFailureOfGestureRecognizer:otherGestureRecognizer];
    return res;
}

#pragma mark - 默认值设置
//重写init 设置默认值
- (instancetype)init{
    if(self = [super init]){
        self.wpEdges = UIRectEdgeAll;
        self.wpNumberOfTapsRequired = 0;
        self.wpNumberOfTouchesRequired = 1;
        self.isCorrected = NO;
    }
    return self;
}

- (instancetype)initWithTarget:(id)target action:(SEL)action{
    if (self = [super initWithTarget:target action:action]) {
        self.wpEdges = UIRectEdgeAll;
        self.wpNumberOfTapsRequired = 0;
        self.wpNumberOfTouchesRequired = 1;
        self.isCorrected = NO;
    }
    return self;
}
@end
上一篇下一篇

猜你喜欢

热点阅读