你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS的手勢識別器

iOS的手勢識別器

編輯:IOS開發綜合

一. 監聽觸摸事件的做法

如果想監聽一個view上面的觸摸事件,不使用手勢實現的步驟
(1). 自定義一個view
(2). 實現view的touches方法,在方法內部實現具體處理代碼

通過touches方法監聽view觸摸事件,有很明顯的幾個缺點
(1). 必須得自定義view
(2). 由於是在view內部的touches方法中監聽觸摸事件,因此默認情況下,無法讓其他外界對象監聽view的觸摸事件
(3). 不容易區分用戶的具體手勢行為

iOS 3.2之後,蘋果推出了手勢識別功能(Gesture Recognizer),在觸摸事件處理方面,大大簡化了開發者的開發難度

二. 手勢識別器簡介

為了完成手勢識別,必須借助於手勢識別器:UIGestureRecognizer

利用UIGestureRecognizer,能輕松識別用戶在某個view上面做的一些常見手勢

UIGestureRecognizer是一個抽象類,定義了所有手勢的基本行為,使用它的子類才能處理具體的手勢

UIGestureRecognizer的子類

UITapGestureRecognizer(敲擊)
UIPinchGestureRecognizer(捏合,用於縮放)
UIPanGestureRecognizer(拖拽)
UISwipeGestureRecognizer(輕掃)
UIRotationGestureRecognizer(旋轉)
UILongPressGestureRecognizer(長按)

三. UIGestureRecognizer的常見屬性和方法

UIGestureRecognizer繼承於NSObject

// 初始化手勢要觸發的對象與事件
- (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action
// 添加手勢要觸發的對象與事件
- (void)addTarget:(id)target action:(SEL)action;
// 移除手勢要觸發的對象與事件
- (void)removeTarget:(nullable id)target action:(nullable SEL)action;

// 手勢狀態
@property(nonatomic,readonly) UIGestureRecognizerState state;
// 代理
@property(nullable,nonatomic,weak) id  delegate;
// 手勢是否可用,默認YES 
@property(nonatomic, getter=isEnabled) BOOL enabled;
// 只讀,手勢所屬的視圖
@property(nullable, nonatomic,readonly) UIView *view;
// 默認YES.意思就是說一旦手勢被識別,那麼就調用[touchView touchesCancelled:withEvent]
@property(nonatomic) BOOL cancelsTouchesInView;
// 默認NO.意思就是再手勢識別成功之前,touchObj還是要分發到touchView.
// 設置為YES的時候就表示從手勢識別成功之前touchObj不給touchView分發
@property(nonatomic) BOOL delaysTouchesBegan;
// 默認YES:在手勢識別成功之前,touchesEnded不會被調用。
// 設置為NO:在手勢識別成功之前,touchesEnded會被調用
@property(nonatomic) BOOL delaysTouchesEnded;

// 當指定的識別器(調用者)識別失敗,才去識別另一個識別器otherGestureRecognizer
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;
// 獲取手勢識別器的觸摸點
- (CGPoint)locationInView:(nullable UIView*)view;
// 獲取手勢識別器的觸摸點個數
- (NSUInteger)numberOfTouches;
// 指定觸摸點的位置
- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view;

四. UIGestureRecognizer代理

注意: 使用多個手勢必須使用代理

// 是否允許觸發手勢
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
// 是否允許多個同時支持多個手勢,默認不允許,手勢必須要設置代理
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

// 這個方法在這兩個gesture recognizers中的任意一個將堵塞另一個的觸摸事件時調用,
// 如果返回YES,則兩個gesture recognizers可同時識別,
// 如果返回NO,則並不保證兩個gesture recognizers必不能同時識別,
// 因為另外一個gesture recognizer的此方法可能返回YES。
// 也就是說兩個gesture recognizers的delegate方法只要任意一個返回YES,則這兩個就可以同時識別;
// 只有兩個都返回NO的時候,才是互斥的。默認情況下是返回NO
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);

// 是否允許手勢識別器識別失敗的時候使用另一個識別器otherGestureRecognizer
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);
// 是否允許接收觸摸點
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
// 是否允許接收長按點
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceivePress:(UIPress *)press;

五. UIGestureRecognizer的子類常見屬性和方法

1. UITapGestureRecognizer(敲擊)

// 需要連續敲擊幾次才可觸發,默認1次
@property (nonatomic) NSUInteger numberOfTapsRequired; 
// 需要幾根手指一起敲擊才可觸發,默認1根
@property (nonatomic) NSUInteger  numberOfTouchesRequired __TVOS_PROHIBITED;

2. UIPinchGestureRecognizer(捏合,用於縮放)

提示: 模擬器快捷鍵:opsin + shift 向上拖“兩個觸摸點”

// 縮放比例
@property (nonatomic) CGFloat scale;
// 縮放速度
@property (nonatomic,readonly) CGFloat velocity;

3. UIPanGestureRecognizer(拖拽)

// 拖動的最短距離
@property (nonatomic) NSUInteger minimumNumberOfTouches __TVOS_PROHIBITED;
// 拖動的最長距離
@property (nonatomic) NSUInteger maximumNumberOfTouches __TVOS_PROHIBITED;
// 在指定的view上得坐標
- (CGPoint)translationInView:(nullable UIView *)view; 
// 設置在view中移動以後的坐標為translation
- (void)setTranslation:(CGPoint)translation inView:(nullable UIView *)view;
// 拖動view,返回的值就用於計算view相對於父控件拖動的速度
- (CGPoint)velocityInView:(nullable UIView *)view;

4. UISwipeGestureRecognizer(輕掃)

// 需要幾根手指一起輕掃才可觸發,默認1根
@property(nonatomic) NSUInteger numberOfTouchesRequired __TVOS_PROHIBITED;
// 設置輕掃方向
@property(nonatomic) UISwipeGestureRecognizerDirection direction;

5. UIRotationGestureRecognizer(旋轉)

// 旋轉角度
@property (nonatomic) CGFloat rotation;
// 旋轉速度
@property (nonatomic,readonly) CGFloat velocity;

6. UILongPressGestureRecognizer(長按)

注意: 長安手勢一般會觸發兩次,所有一般為了只做一次,要做一次判斷

// 需要連續長按幾次才可觸發,默認0次
@property (nonatomic) NSUInteger numberOfTapsRequired;
// 需要幾根手指一起長按才可觸發,默認1根
@property (nonatomic) NSUInteger numberOfTouchesRequired __TVOS_PROHIBITED;
// 最小長按時間
@property (nonatomic) CFTimeInterval minimumPressDuration;
// 允許移動距離
@property (nonatomic) CGFloat allowableMovement;

六. 手勢的具體使用

#import "ViewController.h"

@interface ViewController () 

@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self setUpTap];

    [self setUpLongPress];

    [self setUpSwipe];

    [self setUpRotation];

    [self setUpPinch];

    [self setUpPan];

}


#pragma mark - 點按手勢

- (void)setUpTap {

    UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionUpTap)];

    // 多個手勢必須要代理
    gestureRecognizer.delegate = self;

    [_imageView addGestureRecognizer:gestureRecognizer];
}

- (void)actionUpTap {

    NSLog(@"點按手勢");

}


#pragma mark - 長按手勢

- (void)setUpLongPress {

    UILongPressGestureRecognizer *gestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(actionLongPress)];

    gestureRecognizer.delegate = self;

    [_imageView addGestureRecognizer:gestureRecognizer];
}

- (void)actionLongPress {

    NSLog(@"長按手勢");
}


#pragma mark - 輕掃手勢

- (void)setUpSwipe{

    // 默認向右輕掃,如果要同時有多個輕掃方向,必須要創建輕掃對象
    UISwipeGestureRecognizer *gestureRecognizerRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(actionSwipe)];

    [_imageView addGestureRecognizer:gestureRecognizerRight];

    UISwipeGestureRecognizer *gestureRecognizerLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(actionSwipe)];
    // 向左輕掃
    gestureRecognizerLeft.direction = UISwipeGestureRecognizerDirectionLeft;

    [_imageView addGestureRecognizer:gestureRecognizerLeft];

    UISwipeGestureRecognizer *gestureRecognizerUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(actionSwipe)];
    // 向上輕掃
    gestureRecognizerUp.direction = UISwipeGestureRecognizerDirectionUp;
    [_imageView addGestureRecognizer:gestureRecognizerUp];


    UISwipeGestureRecognizer *gestureRecognizerDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(actionSwipe)];
    // 向下輕掃
    gestureRecognizerDown.direction = UISwipeGestureRecognizerDirectionDown;
    [_imageView addGestureRecognizer:gestureRecognizerDown];

}

- (void)actionSwipe {

    NSLog(@"輕掃手勢");
}


#pragma mark - 旋轉手勢

- (void)setUpRotation {

    UIRotationGestureRecognizer *gestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(actionRotation:)];

    gestureRecognizer.delegate = self;

    [_imageView addGestureRecognizer:gestureRecognizer];
}

- (void)actionRotation:(UIRotationGestureRecognizer *)rotation {

    _imageView.transform = CGAffineTransformRotate(_imageView.transform, rotation.rotation);

    // 復位
    rotation.rotation = 0;
}


#pragma mark - 捏合手勢

- (void) setUpPinch {

    UIPinchGestureRecognizer *gestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(actionPinch:)];

    gestureRecognizer.delegate = self;

    [_imageView addGestureRecognizer:gestureRecognizer];
}

- (void)actionPinch:(UIPinchGestureRecognizer *)pinch {

    _imageView.transform = CGAffineTransformScale(_imageView.transform, pinch.scale, pinch.scale);

    // 復位
    pinch.scale = 1;
}


#pragma mark - 拖拽手勢

- (void)setUpPan {

    UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(actionPan:)];

    gestureRecognizer.delegate = self;

    [_imageView addGestureRecognizer:gestureRecognizer];
}

- (void)actionPan:(UIPanGestureRecognizer *)pan {

    //NSLog(@"%ld",[pan numberOfTouches]);


    // 獲取手勢的觸摸點
    // CGPoint curP = [pan locationInView:self.imageView];

    CGPoint panTrans = [pan translationInView:_imageView];

    _imageView.transform = CGAffineTransformTranslate(_imageView.transform, panTrans.x, panTrans.y);

    // 復位
    [pan setTranslation:CGPointZero inView:_imageView];
}


#pragma mark - 手勢代理

// 是否允許多個同時支持多個手勢,默認不允許,手勢必須要設置代理
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

// 是否允許觸發手勢事件
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    return YES;
}

// 是否允許接收觸摸點
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    return YES;
}

@end
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved