IOS 定義手勢監聽器詳解,利用 UIGestureRecognizer 進行捏合、旋轉、平移、點擊、長按手勢事件響應

IOS中咱們能夠經過UITouch進行觸摸事件監聽,可是UITouch實現捏合、旋轉、長按等手勢事件監聽很是麻煩。IOS中提供 UIGestureRecognizer 的子類幫咱們簡潔等實現捏合、旋轉等特殊手勢監聽。而且一個視圖可添加多個不一樣等手勢監聽器。

開啓userInteractionEnabled

IOS 中UIView 默認是不可響應事件的,咱們須要開啓 userInteractionEnabled 方可進行事件響應。下面代碼中咱們建立了一個圖片視圖,而且開始事件響應。UIView 經過 addGestureRecognizer 進行添加手勢監聽器和 removeGestureRecognizer 刪除手勢監聽器
// 建立圖片視圖
- (void) creareImg {
    UIImage* image = [UIImage imageNamed:@"zz.jpeg"];
    _imageView = [[UIImageView alloc] initWithImage:image];
    UIScreen* screen = [UIScreen mainScreen];
    const int width = 200;
    const int height = 100;
    const float x = screen.bounds.size.width / 2 - width / 2;
    const float y = screen.bounds.size.height / 2 - height;
    _imageView.frame = CGRectMake(x, y, width, height);
    _imageView.userInteractionEnabled = YES;
    [self.view addSubview:_imageView];
}

瞭解UIGestrueRecognizer

在開始使用自定義手勢以前咱們先了解一下 UIGestrueRecognizer 的,由於自定義都是基於 UIGestrueRecognizer 繼承實現的。 UIGestrueRecognizer 是一個手勢監聽器,它能夠設置多個手指同時觸發觸發事件等行爲。它具備代理協議 UIGestureRecognizerDelegate 下面我來看一下它主要的屬性和API、代理方法。
屬性
名稱 類型 說明 默認值
state UIGestureRecognizerState 當前手勢狀態,可分爲手勢開始,手勢改變,手勢結束等等
enabled BOOL 是否啓用 YES
view UIView 手勢監聽的視圖
requiresExclusiveTouchType BOOL 是否忽略其餘手勢類型,設置爲YES將只響應一種手勢類型 NO
numberOfTouches NSUInteger 多少根手指觸發手勢 1
API
  • - (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 刪除事件監聽函數
  • - (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer 添加其餘手勢衝突失效器,當觸發當前手勢時,指定的手勢將失效。
  • - (CGPoint)locationInView:(nullable UIView*)view 獲取相對於指定視圖的座標位置
  • - (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view 獲取指定手指相對指定視圖的座標位置
代理協議
  • - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 手勢準備開啓時候觸發,返回NO則取消手勢。
  • - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 當手勢與其餘手勢同時發生識別時候觸發,返回YES運行兩個手勢同時進行,返回NO則阻止同時識別。
  • - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 是否給事件接收手指。在手勢開始觸發事件觸發前觸發,返回NO能夠阻止事件獲取觸摸的手指。
  • - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceivePress:(UIPress *)press 是否給按下事件接收手指,在按下手勢事件觸發前觸發。返回NO可阻止事件獲取觸摸的手指。
咱們瞭解清除GestureRecognizer 類,下面咱們來了解其子類手勢的使用。

UITapGestureRecognizer 點擊手勢

點擊手勢,可設置手指數量、點擊次數觸發的手勢
// 建立點擊手勢
- (void) createTapGes {
    _imageView.userInteractionEnabled = YES; // 開啓響應事件屬性
    UITapGestureRecognizer* tapOneGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(big)]; // 建立手勢
    tapOneGes.numberOfTapsRequired = 1; // 觸發事件的點擊次數
    tapOneGes.numberOfTouchesRequired = 1; // 觸發事件的手指數量
    [_imageView addGestureRecognizer:tapOneGes]; // 添加手勢監聽器
}
// 點擊觸發事件
- (void) big {
    UIScreen* screen = [UIScreen mainScreen];
    [UIView beginAnimations:nil context:nil]; // 開始佈局動畫
    _imageView.frame = CGRectMake(0, 0, screen.bounds.size.width, screen.bounds.size.height);
    [UIView commitAnimations]; // 結束佈局動畫
}

UIPinchGestureRecognizer 捏合手勢

捏合手勢,表示雙指捏合縮放的手勢觸發。經常使用於對圖片查看縮放事件監聽
// 捏合手勢
- (void) createPinchGes {
    UIPinchGestureRecognizer* pinch = [[UIPinchGestureRecognizer alloc] init]; // 建立手勢
    [pinch addTarget:self action:@selector(scale:)]; // 添加事件函數
    pinch.delegate = self; // 設置代理
    [_imageView addGestureRecognizer:pinch]; // 視圖添加手勢監聽器
}

- (void) scale: (UIPinchGestureRecognizer*) pinch {
    UIView* IView = pinch.view; // 獲取監聽的視圖
    CGAffineTransform transiform = CGAffineTransformScale(IView.transform, pinch.scale, pinch.scale); // 計算縮放後的矩陣
    if (transiform.a < 0.4) { // 縮放小於0.4阻止
        transiform.a = 0.4;
        transiform.d = 0.4;
    }
    IView.transform = transiform; // 從新設置矩陣
    pinch.scale = 1; // 重置縮放矩陣,不然手勢會一直累加
}

// 添加容許多個手勢觸發代理函數
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return  YES;
}

上面代碼中咱們經過獲取捏合手勢的scale 屬性獲取用戶捏合縮放的大小。而且使用內置api CGAffineTransformScale 從新計算了視圖的2D矩陣(矩陣表示圖像變形,能夠了解一下圖形學),注意!最後一步中必須重置手勢的scale 不然會一直累加致使計算矩陣錯誤,若是不想重置的話那就須要修改 CGAffineTransformScale 的第一個參數爲基礎矩陣參數。api

UIRotationGestureRecognizer 旋轉手勢

旋轉手勢,可獲取用戶手指旋轉的角度。
// 旋轉手勢
- (void) createRotateGes {
    UIRotationGestureRecognizer* rotate = [[UIRotationGestureRecognizer alloc] init];
    [rotate addTarget:self action:@selector(rotate:)];
    rotate.delegate = self;
    [_imageView addGestureRecognizer:rotate];
}
// 旋轉觸發事件
- (void) rotate: (UIRotationGestureRecognizer*) rotate {
    UIView* IView = rotate.view;
    IView.transform =  CGAffineTransformRotate(IView.transform, rotate.rotation); // 從新計算視圖矩陣
    rotate.rotation = 0;
}

UIPanGestureRecognizer 平移手勢

平移動手勢,比較簡單就是手指移動時候觸發,可是提供平移的位置和平移的速度
// 平移手勢
- (void) createPanGes {
    UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
    pan.delegate = self;
    [_imageView addGestureRecognizer:pan];
}
- (void) pan: (UIPanGestureRecognizer*)pan {
    CGPoint speed = [pan velocityInView:_imageView]; // 獲取移動速度
    NSLog(@"x速度= %f, y速度= %f", speed.x, speed.y);
    CGPoint translation = [pan translationInView:_imageView]; // 獲取移動矩陣
    CGAffineTransform transform = CGAffineTransformTranslate(_imageView.transform, translation.x, translation.y);
    _imageView.transform = transform;
}

UILongPressGestureRecognizer 長按手勢

長按對應視圖觸發手勢,可設置手指數量和手指長按時間
// 長按手勢
- (void) createLongPassGes {
    UILongPressGestureRecognizer* longPass = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(pass:)];
    longPass.minimumPressDuration = 1; // 設置長按觸發時間,默認0.5
    [_imageView addGestureRecognizer: longPass];
}

- (void)pass: (UILongPressGestureRecognizer*) longPass {
    if (longPass.state == UIGestureRecognizerStateBegan) {
        NSLog(@"開始長按");
    } else if (longPass.state == UIGestureRecognizerStateEnded) {
        NSLog(@"結束長按");
    } else if (longPass.state == UIGestureRecognizerStateChanged) {
        NSLog(@"長按發生改變");
    }
}

UISwipeGestureRecognizer 輕滑手勢

輕滑手勢,相似咱們的平移手勢。可是輕滑不一樣的是在用戶快速滑動時候速度,而且只提供滑動方向。
// 建立輕滑手勢
- (void) createSwipe {
    UISwipeGestureRecognizer* swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swiper:)];
    swipe.direction = UISwipeGestureRecognizerDirectionDown;
    [_imageView addGestureRecognizer: swipe];
    swipe.delegate = self;
}

- (void) swiper: (UISwipeGestureRecognizer*)swiper {
    NSLog(@"發生向下滑動");
}
相關文章
相關標籤/搜索