iOS 觸摸事件五:手勢處理器

通過touches方法監聽觸摸事件,不容易區分用戶的具體手勢行爲。爲此,蘋果推出了手勢處理器(UIGestureRecognizer)。手勢處理器處理用戶觸摸事件更加簡單,而且無論處理哪種觸摸手勢,都可以面向GestureRecognizer編程。個人認爲手勢處理器即爲手勢觸摸四個方法的一種封裝。
平時我們使用手勢處理器一般不直接使用UIGestureRecognizer,而是使用UIGesturerecognizer提供的六大子類來處理具體的手勢:
- UITapGestureRecognizer: 處理用戶點擊手勢的手勢處理器
- UIPinchGestureRecognizer: 處理用戶捏合手勢的手勢處理器
- UIPanGestureRecognizer: 處理用戶拖拽手勢的手勢處理器
- UISwipeGestureRecognizer: 處理用戶輕掃手勢的手勢處理器
- UIRotationGestureRecognizer: 處理用戶旋轉手勢的手勢處理器

手勢處理器的處理用戶觸摸手勢的步驟:

  1. 根據程序要處理的手勢創建對應的手勢處理器對象。創建手勢處理器時需要指定target和action參數(當該控件上發生觸摸手勢後,該Target對象的action方法將會被激發,即目標-行爲模式)
  2. 如果該UI控件不允許用戶交互,則將該UI控件的userInteractionEnabled的屬性設置爲YES; 如果希望該空間可支持多點觸摸,還需要將mutipleTouchEnable(是否多點觸摸)設置爲YES
  3. 調用該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*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章