通過touches方法監聽觸摸事件,不容易區分用戶的具體手勢行爲。爲此,蘋果推出了手勢處理器(UIGestureRecognizer)。手勢處理器處理用戶觸摸事件更加簡單,而且無論處理哪種觸摸手勢,都可以面向GestureRecognizer編程。個人認爲手勢處理器即爲手勢觸摸四個方法的一種封裝。
平時我們使用手勢處理器一般不直接使用UIGestureRecognizer,而是使用UIGesturerecognizer提供的六大子類來處理具體的手勢:
- UITapGestureRecognizer: 處理用戶點擊手勢的手勢處理器
- UIPinchGestureRecognizer: 處理用戶捏合手勢的手勢處理器
- UIPanGestureRecognizer: 處理用戶拖拽手勢的手勢處理器
- UISwipeGestureRecognizer: 處理用戶輕掃手勢的手勢處理器
- UIRotationGestureRecognizer: 處理用戶旋轉手勢的手勢處理器
手勢處理器的處理用戶觸摸手勢的步驟:
- 根據程序要處理的手勢創建對應的手勢處理器對象。創建手勢處理器時需要指定target和action參數(當該控件上發生觸摸手勢後,該Target對象的action方法將會被激發,即目標-行爲模式)
- 如果該UI控件不允許用戶交互,則將該UI控件的userInteractionEnabled的屬性設置爲YES; 如果希望該空間可支持多點觸摸,還需要將mutipleTouchEnable(是否多點觸摸)設置爲YES
- 調用該UI控件的addGestureRecognizer:方法添加該手勢處理器
UIGestureRecognizer提供的一些常用方法和屬性:
UIGestureRecognizer作爲所有手勢處理器的基類,提供了一些常用的方法和屬性:
- (CGPoint)locationInView:(UIView*)view; //返回該手勢在view控件中的觸摸位置
- (NSUInteger)numberOfTouches; // 返回該手勢包含觸摸點的數量(就是用戶用了幾個手指進行觸摸)
- view: 返回激發該收拾的UI控件
- enabled: 用於設置和返回該手勢處理器是否可用
- state: 只讀,獲取該收拾的狀態,(枚舉值)比如
手勢剛剛開始處於UIGestureRecognizerStateBegan狀態
手勢改變時處於UIGestureRecognizerStateChanged狀態
手勢結束時處於UIGestureRecognizerStateEnded狀態
UITapGestureRecognizer:
點擊手勢的手勢處理器,繼承了UIGEstureRecognizer類,除了擁有父類的屬性方法外,還提供瞭如下的兩個屬性:
numberOfTapsRequired: 指定該手勢處理器只處理幾次觸摸事件,默認是1
numberOfTouchesRequired: 指定該手勢處理器只能處理幾個手指觸摸事件,默認是1
使用:
1. 創建Tap手勢
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selecor(handlePanGesture:)];
//對手勢進行初始化,並指定出發該手勢時的所出發(調用)的handlePanGesture:方法。 同時會傳遞一個UIPanGestureRecognizer類型的參數
2. 對手勢的設置(可選)
tapGesture.numberOfTouchesRequired = 1;//設置手勢需要的觸點的數量
tapGesture.numberOfTapsRequired = 1; //設置手勢需要點擊的次數
3. 將手勢添加到UI控件上
//調用UIView的addGestureRecognizer:方法即可
[self.view addGestureRecognizer:tapGesture];
//手勢觸發時調用的方法
-(void)handlePanGesture:(UIPanGestureRecognizer *)gesture{
NSLog(@"點擊手勢");
}
UIPinchGestureRecognizer:
捏合手勢,同樣繼承了UIRespond類,使用步驟和點擊手勢處理器完全相同,額外增加了兩個屬性來獲取相關信息:
scale :獲取捏合的比例
velocity : 獲取捏合的速度
捏合手勢一般用於圖片的縮放。處理是要設置一下,避免縮放的速度過快。
使用:
//打開imgView的交互
_imgView.userInteractionEnabled = YES;
//打開imgView多點觸摸 ,前提,多觸點事件,要打開控件的多點觸摸
_imgView.multipleTouchEnabled = YES;
//創建手勢, target-action
UIPinchGestureRecognizer *gesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
//爲imgView添加手勢
[_imgView addGestureRecognizer:gesture];
}
//手勢處理函數
-(void)handlePinch:(UIPinchGestureRecognizer *)gesture{
//手勢處理
NSLog(@"縮放。。");
//獲取捏合的比例
CGFloat scale = gesture.scale;
//直接縮放
// _imgView.transform = CGAffineTransformMakeScale(scale, scale); //--第二次縮放時回到原來
//相對某個tranform進行縮放-- 在原有的基礎上進行縮放
_imgView.transform = CGAffineTransformScale(_imgView.transform, scale, scale) ;//--縮放的速度太快
//優化。讓縮放比例變爲1,避免縮放過快
gesture.scale = 1.0f;
}
UIPanGestureRecognizer:
拖拽手勢, 該手勢設置相關信息的屬性:
maximumNumberOfTouches: 設置該手勢處理器最多支持幾個手指拖動
minimumNumberOfTouches: 設置該手勢處理器最少需要幾個手指拖動
translationInView: 獲取拖動手勢在指定控件上的位移。該方法返回一個CGPoint類型,該結構體中的x值代表水平方向的位移,y的值代表垂直方向上的位移
velocityInView: 獲取該拖動手勢在指定控件上的拖動速度,該方法返回一個CGPoint類型,該結構體中的x值代表水平方向的移動速度,y的值代表垂直方向上的移動速度
`
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
pan.maximumNumberOfTouches = 3; //設置手勢最多支持3個手指觸點
pan.minimumNumberOfTouches = 1; //設置手勢至少1個手指觸點
[_imgView addGestureRecognizer:pan];
}
-(void)handleAction:(UIPanGestureRecognizer *)gesture{
CGPoint offSet = [gesture translationInView:_imgView];
//判斷邊界
_imgView.transform = CGAffineTransformTranslate(_imgView.transform, offSet.x, offSet.y);
[gesture setTranslation:CGPointMake(0,0) inView:_imgView];
}
`
UISwipeGestureRecognizer:
輕掃手勢,獲取與輕掃相關的信息:
numberOfTouchesRequired: 設置該手勢只處理幾個手指的觸摸事件
direction: 設置該手勢處理器只處理某個方向的輕掃,該屬性支持上、下、左、右4個枚舉值,一個手勢處理器只能設置一個方向
示例 `- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(SCREEN.size.width/2-32, SCREEN.size.height/2-32, 32,32)];
imgView.image = [UIImage imageNamed:@"a0_.9.png"];
UISwipeGestureRecognizer *swip = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip.numberOfTouchesRequired = 1; //需要一個觸點
swip.direction = UISwipeGestureRecognizerDirectionUp;
UISwipeGestureRecognizer *swip1 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip1.numberOfTouchesRequired = 1; //需要一個觸點
swip1.direction = UISwipeGestureRecognizerDirectionRight;
UISwipeGestureRecognizer *swip2 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip2.numberOfTouchesRequired = 1; //需要一個觸點
swip2.direction = UISwipeGestureRecognizerDirectionDown;
UISwipeGestureRecognizer *swip3 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip3.numberOfTouchesRequired = 1; //需要一個觸點
swip3.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addSubview:imgView];
[self.view addGestureRecognizer:swip];
[self.view addGestureRecognizer:swip1];
[self.view addGestureRecognizer:swip2];
[self.view addGestureRecognizer:swip3];
}
-(void)handleAction:(UISwipeGestureRecognizer *)gesture{
CGRect rect = imgView.frame;
NSLog(@"rect.x = %.2f, rect.y = %.2f", rect.origin.x, rect.origin.y);
if(gesture.direction == UISwipeGestureRecognizerDirectionUp ){
//向上
NSLog(@"向上");
if(rect.origin.y >= 120){
rect.origin.y -= 20;
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到頭了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
[alert show];
}
}
if(gesture.direction == UISwipeGestureRecognizerDirectionRight){
//向右
NSLog(@"向右");
if(rect.origin.x+32 <= 270){
rect.origin.x += 20;
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到頭了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
[alert show];
}
}
if(gesture.direction == UISwipeGestureRecognizerDirectionDown){
//向下
NSLog(@"向下");
if(rect.origin.y+32 <= 500){
rect.origin.y += 20;
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到頭了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
[alert show];
}
}
if(gesture.direction == UISwipeGestureRecognizerDirectionLeft){
//向左
NSLog(@"向左");
if(rect.origin.x >= 20){
rect.origin.x -= 20;
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到頭了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
[alert show];
}
}
imgView.frame = rect;
}`
UIRotationGestureRecognizer:
旋轉手勢,額外定義了2個屬性來獲取旋轉的相關信息:
rotation: 獲取旋轉的角度
velocity: 獲取旋轉的速度
旋轉手勢同樣經常用於圖片的旋轉處理,同樣優化一下,避免旋轉過快
使用與上類似:
- (void)viewDidLoad {
[super viewDidLoad];
UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)];
_imgView.userInteractionEnabled = YES; _imgView.multipleTouchEnabled = YES;
[_imgView addGestureRecognizer:rotation];
}
-(void)handleRotation:(UIRotationGestureRecognizer *)gesture{
NSLog(@"旋轉");
//獲取旋轉的角度
CGFloat rotation = gesture.rotation;
//對圖片進行旋轉
_imgView.transform = CGAffineTransformRotate(_imgView.transform, rotation);
//優化,避免旋轉過快
gesture.rotation = 0.0f;
}
UILongPressGestureRecognizer:
長按手勢,設置相關信息的屬性:
minmumPressDuration: 指定用戶至少在屏幕上按下多少秒纔會觸發長按手勢,默認值是0.5秒
allowableMovement:指定該長按手勢允許用戶移動手指的最大距離。如果用戶手指按下時的移動距離超過了該距離,則長按手勢失效
numberOfTouchesRequired: 指定必須使用幾個手指在屏幕上長按纔會觸發該手勢
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//定義3個自定義的菜單項
transmitItem = [[UIMenuItem alloc] initWithTitle:@"轉發" action:@selector(transmitClick:)];
deleteItem = [[UIMenuItem alloc] initWithTitle:@"刪除" action:@selector(deleteClick:)];
reportItem = [[UIMenuItem alloc] initWithTitle:@"舉報" action:@selector(reportClick:)];
//創建手勢處理器,指定該控制器使用的行爲方法
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressAction:)];
_imgView.userInteractionEnabled = YES;
//爲視圖添加手勢
[_imgView addGestureRecognizer:longPressGesture];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*自定義菜單項的點擊事件*/
-(void)transmitClick:(id)sender{
NSLog(@"點擊轉發");
}
-(void)deleteClick:(id)sender{
NSLog(@"點擊刪除");
}
-(void)reportClick:(id)sender{
NSLog(@"點擊舉報");
}
/*end*/
/*手勢處理器的action函數, 當該方法被激活時,手勢處理器會作爲參數傳遞給該方法的參數*/
-(void)handleLongPressAction:(UILongPressGestureRecognizer *)gesture{
//"開始觸摸狀態"時進入
if(gesture.state == UIGestureRecognizerStateBegan){
NSLog(@"長按手勢觸發");
[self becomeFirstResponder];
//創建一個menu控制器
UIMenuController *menu = [UIMenuController sharedMenuController];
menu.menuItems = @[transmitItem, deleteItem, reportItem];
//懸浮在哪一個view上(定位Menu)並確定其大小
CGRect rect = CGRectMake(0, 0, 100, 50);
[menu setTargetRect:rect inView:_imgView];
//展示Menu
[menu setMenuVisible:YES];
}
}
/*end*/