你真的瞭解UIGestureRecognizer嗎?

来源:http://www.cnblogs.com/wujy/archive/2016/08/30/5821991.html
-Advertisement-
Play Games

一:首先查看一下關於UIGestureRecognizer的定義 UIGestureRecognizer是一個抽象類,定義了所有手勢的基本行為,使用它的子類才能處理具體的手勢 知識點1:關於UIGestureRecognizer的子類如下(下麵這些才是我們平常會直接運用到的類): 實例如下: 二:關 ...


一:首先查看一下關於UIGestureRecognizer的定義

//當前手勢狀態
typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
    //尚未識別是何種手勢操作(但可能已經觸發了觸摸事件),預設狀態
    UIGestureRecognizerStatePossible,   
    //手勢已經開始,此時已經被識別,但是這個過程中可能發生變化,手勢操作尚未完成
    UIGestureRecognizerStateBegan,     
    //手勢狀態發生改變
    UIGestureRecognizerStateChanged, 
    // 手勢識別操作完成(此時已經鬆開手指)  
    UIGestureRecognizerStateEnded, 
    //手勢被取消,恢復到預設狀態   
    UIGestureRecognizerStateCancelled, 
    //手勢識別失敗,恢復到預設狀態
    UIGestureRecognizerStateFailed,    
    //手勢識別完成,同end
    UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded 
};

NS_CLASS_AVAILABLE_IOS(3_2) @interface UIGestureRecognizer : NSObject

//創建一個手勢對象並添加觸發事件
- (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action NS_DESIGNATED_INITIALIZER; 
//給一個手勢對象添加監聽事件
- (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 <UIGestureRecognizerDelegate> delegate; 
//手勢識別是否可用
@property(nonatomic, getter=isEnabled) BOOL enabled;  
//獲取手勢觸摸的View視圖 只讀
@property(nullable, nonatomic,readonly) UIView *view;         
//是否取消觸摸控制項的響應
預設為YES,這種情況下當手勢識別器識別到觸摸之後,會發送touchesCancelled給觸摸到的控制項以取消控制項view對touch的響應,這個時候只有手勢識別器響應touch,當設置成NO時,手勢識別器識別到觸摸之後不會發送touchesCancelled給控制項,這個時候手勢識別器和控制項view均響應touch。
註意:手勢識別和觸摸事件是同時存在的,只是因為touchesCancelled導致觸摸事件失效、
@property(nonatomic) BOOL cancelsTouchesInView; 
      
//是否延遲發送觸摸事件給觸摸到的控制項
預設是NO,這種情況下當發生一個觸摸時,手勢識別器先捕捉到到觸摸,然後發給觸摸到的控制項,兩者各自做出響應。如果設置為YES,手勢識別器在識別的過程中(註意是識別過程),不會將觸摸發給觸摸到的控制項,即控制項不會有任何觸摸事件。只有在識別失敗之後才會將觸摸事件發給觸摸到的控制項,這種情況下控制項view的響應會延遲約0.15ms。
@property(nonatomic) BOOL delaysTouchesBegan;     
  
//如果觸摸識別失敗是否立即結束本次手勢識別的觸摸事件
@property(nonatomic) BOOL delaysTouchesEnded;        

//指定一個手勢需要另一個手勢執行失敗才會執行,同時觸發多個手勢使用其中一個手勢的解決辦法
有時手勢是相關聯的,如單機和雙擊,點擊和長按,點下去瞬間可能只會識別到單擊無法識別其他,該方法可以指定某一個 手勢,即便自己已經滿足條件了,也不會立刻觸發,會等到該指定的手勢確定失敗之後才觸發
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;

//獲取當前觸摸在指定視圖上的點
- (CGPoint)locationInView:(nullable UIView*)view;                               

//獲取觸摸手指數
- (NSUInteger)numberOfTouches;                                         

//多指觸摸的觸摸點相對於指定視圖的位置
- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view; 

@end

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

知識點1:關於UIGestureRecognizer的子類如下(下麵這些才是我們平常會直接運用到的類):

UITapGestureRecognizer(輕觸,點按)
UILongPressGestureRecognizer(長按)
UISwipeGestureRecognizer(輕掃手勢)
UIRotationGestureRecognizer(旋轉手勢)
UIPanGestureRecognizer(拖拽手勢)
UIPinchGestureRecognizer(捏合手勢,縮放用)

實例如下:

//拖拽手勢
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[tagButton addGestureRecognizer:pan];


- (void)pan:(UIPanGestureRecognizer *)pan
{
             
}
//給視圖增加點擊動作

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapHandle:)];
[self.view addGestureRecognizer:tap];


-(void)tapHandle:(UITapGestureRecognizer*)tap
{
    
}

二:關於UIGestureRecognizerDelegate代理的內容

@protocol UIGestureRecognizerDelegate <NSObject>
@optional

//開始進行手勢識別時調用的方法,返回NO則結束識別,不再觸發手勢,用處:可以在控制項指定的位置使用手勢識別
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;

//是否支持多手勢觸發,返回YES,則可以多個手勢一起觸發方法,返回NO則為互斥
是否允許多個手勢識別器共同識別,一個控制項的手勢識別後是否阻斷手勢識別繼續向下傳播,預設返回NO;如果為YES,響應者鏈上層對象觸發手勢識別後,如果下層對象也添加了手勢併成功識別也會繼續執行,否則上層對象識別後則不再繼續傳播
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

// 這個方法返回YES,第一個手勢和第二個互斥時,第一個會失效
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);

//這個方法返回YES,第一個和第二個互斥時,第二個會失效
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);

//手指觸摸屏幕後回調的方法,返回NO則不再進行手勢識別,方法觸發等
此方法在window對象在有觸摸事件發生時,調用gesture recognizer的touchesBegan:withEvent:方法之前調用,如果返回NO,則gesture recognizer不會看到此觸摸事件。(預設情況下為YES)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;

@end

知識點1:

//是否同時支持多種手勢
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
  return YES;
}

//是否允許開始點擊
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
return YES;
}
//設置點擊的範圍
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
//獲取當前的觸摸點
  CGPoint curp = [touch locationInView:self.imageView];
  if (curp.x <= self.imageView.bounds.size.width*0.5) {
      return NO;
  }else{

      return YES;
  }
}

知識點2UITapGestureRecognizer和UIButton的點擊事件衝突的解決辦法

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{    
if ([touch.view isKindOfClass:[UIButton class]])    { 
       return NO;    }   
       return YES;
}

三:關於UIGestureRecognizer的子類知識

1:UITapGestureRecognizer(輕觸,點按)

NS_CLASS_AVAILABLE_IOS(3_2) @interface UITapGestureRecognizer : UIGestureRecognizer

//設置能識別到手勢的最少的輕觸次數(預設為1)
@property (nonatomic) NSUInteger  numberOfTapsRequired;     
//設置能識別到手勢的最少的手指的個數(預設為1) 
@property (nonatomic) NSUInteger  numberOfTouchesRequired;  
@end

知識點1:實例代碼如下

// 創建一個手勢對象
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
// 設置能識別到手勢的最少的輕觸次數
tap.numberOfTapsRequired = 3;
// 設置能識別到手勢的最少的手指的個數
tap.numberOfTouchesRequired = 2;
//把手勢對象添加到對應的控制項中
[self.imgView addGestureRecognizer:tap];

2:UILongPressGestureRecognizer(長按手勢)

NS_CLASS_AVAILABLE_IOS(3_2) @interface UILongPressGestureRecognizer : UIGestureRecognizer
//設置能識別到手勢的最少的輕觸次數(預設為1)
@property (nonatomic) NSUInteger numberOfTapsRequired;     
//設置能識別到手勢的最少的手指的個數(預設為1) 
@property (nonatomic) NSUInteger numberOfTouchesRequired;   
//設置能識別到長按手勢的最短的長按時間,單位:秒,預設為0.5
@property (nonatomic) CFTimeInterval minimumPressDuration; 
//設置長按時允許移動的最大距離,單位:像素,預設為10像素
@property (nonatomic) CGFloat allowableMovement;           

@end

知識點1:實例代碼如下

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressAction:)];
// 設置能識別到長按手勢的最小的長按時間
longPress.minimumPressDuration = 0.5;
// "容錯的範圍"
longPress.allowableMovement  = 10;
// 把長按手勢添加到對應的控制項中
[self.imgView addGestureRecognizer:longPress];

3:UISwipeGestureRecognizer(輕掃手勢)

typedef NS_OPTIONS(NSUInteger, UISwipeGestureRecognizerDirection) {
    UISwipeGestureRecognizerDirectionRight = 1 << 0,  //向右滑
    UISwipeGestureRecognizerDirectionLeft  = 1 << 1,  //向左滑
    UISwipeGestureRecognizerDirectionUp    = 1 << 2,  //向上滑
    UISwipeGestureRecognizerDirectionDown  = 1 << 3  //向下滑
};

NS_CLASS_AVAILABLE_IOS(3_2) @interface UISwipeGestureRecognizer : UIGestureRecognizer 
//最少觸摸手指個數,預設為1
@property(nonatomic) NSUInteger                        numberOfTouchesRequired; 
//設置輕掃手勢支持的方向,預設為向右滑
@property(nonatomic) UISwipeGestureRecognizerDirection direction;               

@end

知識點1:實例代碼如下

UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeAction:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.imgView addGestureRecognizer:swipeLeft];

4:UIRotationGestureRecognizer(旋轉手勢)

NS_CLASS_AVAILABLE_IOS(3_2) @interface UIRotationGestureRecognizer : UIGestureRecognizer
//旋轉的角度
@property (nonatomic)          CGFloat rotation;  
//旋轉速度,單位:度/秒、         
@property (nonatomic,readonly) CGFloat velocity;           

@end

知識點1:實例代碼如下

//為圖片框添加一個旋轉手勢
UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotateAction:)];rotation.delegate = self;
[self.imgView addGestureRecognizer:rotation];


// 旋轉手勢的監聽方法
- (void)rotateAction:(UIRotationGestureRecognizer *)recognizer {
// 在原來的基礎上, 累加多少度
recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
// 每次旋轉完畢後將rotation的值, 恢復到0的位置.recognizer.rotation = 0;
}

5:UIPanGestureRecognizer(拖拽手勢)

NS_CLASS_AVAILABLE_IOS(3_2) @interface UIPanGestureRecognizer : UIGestureRecognizer 
//設置觸發拖拽最少手指數,預設為1
@property (nonatomic)          NSUInteger minimumNumberOfTouches;   
//設置觸發拖拽最多手指數,預設為 UINT_MAX 無限大
@property (nonatomic)          NSUInteger maximumNumberOfTouches;   
//獲取當前拖拽位置
- (CGPoint)translationInView:(nullable UIView *)view;                        
//設置當前拖拽位置
- (void)setTranslation:(CGPoint)translation inView:(nullable UIView *)view;
//設置拖拽速度,單位:像素/秒
- (CGPoint)velocityInView:(nullable UIView *)view;                          

@end

知識點1:實例代碼

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
[self.imgView addGestureRecognizer:pan];


// 拖拽手勢的監聽方法
- (void)panAction:(UIPanGestureRecognizer *)recognizer {
// 1. 獲取手指拖拽的時候, 平移的值
CGPoint translation = [recognizer translationInView:recognizer.view];
// 2. 讓當前控制項做響應的平移
recognizer.view.transform = CGAffineTransformTranslate(recognizer.view.transform, translation.x, translation.y);
// 3. 每次平移手勢識別完畢後, 讓平移的值不要累加
[recognizer setTranslation:CGPointZero inView:recognizer.view];
}

6:UIPinchGestureRecognizer(捏合手勢,縮放用)

NS_CLASS_AVAILABLE_IOS(3_2) @interface UIPinchGestureRecognizer : UIGestureRecognizer 

//設置縮放比例
@property (nonatomic)          CGFloat scale;     
//獲取捏合速度,單位:縮放比/秒         
@property (nonatomic,readonly) CGFloat velocity;            

@end

知識點1:實例代碼

UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchAction:)];
pinch.delegate = self;
[self.imgView addGestureRecognizer:pinch];



// 捏合手勢監聽方法
- (void)pinchAction:(UIPinchGestureRecognizer *)recognizer {
recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);
recognizer.scale = 1.0;
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一:首先查看一下關於UIApplication的定義 UIApplication的核心作用是提供了iOS程式運行期間的控制和協作工作。它的基類是UIResponder;每一個程式在運行期必須有且僅有一個UIApplication(或則其子類)的一個實例;在程式開始運行的時候,UIApplicatio ...
  • Swift - 計算文本高度 效果 源碼 ...
  • #import <UIKit/UIKit.h> @interface SearchBar : UITextField @property (nonatomic,strong) UIButton *button; + (instancetype)searchBar; @end #import "Sea ...
  • //這裡設置游標位置,讓游標位置後移10 textField.leftView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 10, 0)]; textField.leftViewMode = UITextFieldViewModeAlways; ...
  • 一:UIViewController模態跳轉 知識點1: a: 在官方文檔中,建議這兩者之間通過delegate實現交互。例如使用UIImagePickerController從系統相冊選取照片或者拍照,imagePickerController和彈出它的VC之間就通過UIImagePickerCo ...
  • 廢話不多說,先看上效果,由於動畫錄製的時候幀率限制,只能將動畫放慢了進行錄製,更容易看到效果 這是點擊開始之後代碼 由於動畫使由多個動畫組成,所以第一個動畫完畢之後自動再次開始一個動畫 先解釋一下動畫執行過程 第一步是通過CABasicAnimation 對照片進行縮放 第二步是通過CAKeyfra ...
  • 很久沒有總結,回頭看了一下過期的賬號,記錄的內容少之又少。最近有一些時間,想好好總結記錄一下。 由於很久沒有記錄,想寫的東西很多又很雜,想了一下,一篇一篇羅列知識點和經驗,還不如寫一個系列,記錄一個應用的開發流程和經歷。 主線就是一個應用的構建和開發過程,期間再針對部分節點進行分析和探討。 這篇的標 ...
  • 一:首先瞭解一下生命周期圖 二:UIViewController 生命周期介紹 1.通過alloc init 分配記憶體,初始化controller. 2.loadView loadView方法預設實現[super loadView] 如果在初始化controller時指定了xib文件名,就會根據傳入 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...