iOS 使用手勢UIGestureRecognizer對圖像進行縮放、移動、旋轉等操作


原文  http://blog.csdn.net/crayondeng/article/details/8760134

UIGestureRecognizer 類

該類擁有一系列子類,每個子類都用於識別某類指定的手勢。它們是:

  • UITapGestureRecognizer – “輕擊”手勢。可以配置爲“單擊”和“連擊”的識別。

  • UIPinchGestureRecognizer –“捏合”手勢。該手勢通常用於縮放視圖或改變可視組件的大小。

  • UIPanGestureRecognizer – “平移”手勢。識別拖拽或移動動作。

  • UISwipeGestureRecognizer – “輕掃”手勢。當用戶從屏幕上劃過時識別爲該手勢。可以指定該動作的方向(上、下、左、右)。

  • UIRotationGestureRecognizer – “轉動”手勢。用戶兩指在屏幕上做相對環形運動。

  • UILongPressGestureRecognizer – “長按”手勢。使用一指或多指觸摸屏幕並保持一定時間。

這些手勢識別器必需和視圖通過addGestureRecognizer:方法聯繫在一起。識別器必需指定一個響應方法以便發生指定手勢時進行調用。removeGestureRecognizer:方法可以將識別器從視圖中移出,方法參數指定要移除的識別器。

下面通過一個實例程序來分別介紹這些手勢,在一個視圖中增加一個UIImageView控件,添加一個圖像。對圖像的操作都基於此視圖中進行分別對這個圖像使用這些手勢。

一、首先在一個視圖中添加一個imageview控件,用以添加一個圖像。
self.productImageView.image = [UIImage imageNamed:@"iPhone.jpg"];  
二、tap 手勢 (輕擊)
說明:在單擊中,實現的是視圖恢復,在雙擊中實現的是視圖放大/縮小一倍。
//輕點  
      
   // 單擊  
    UITapGestureRecognizer *SingleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(resetImage:)];  
    SingleTapGesture.numberOfTapsRequired = 1;//tap次數  
    [self.view addGestureRecognizer:SingleTapGesture];  
    // 雙擊  
    UITapGestureRecognizer *doubleTapGesture;  
    doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTapFrom)];  
    doubleTapGesture.numberOfTapsRequired = 2;   
    [self.view addGestureRecognizer:doubleTapGesture];  
    // 關鍵在這一行,如果雙擊確定偵測失敗才會觸發單擊  
    [SingleTapGesture requireGestureRecognizerToFail:doubleTapGesture];  
響應方法
//單擊恢復視圖  
- (void)resetImage:(UITapGestureRecognizer *)recognizer  
{  
    [UIView beginAnimations:nil context:nil];  
    [UIView setAnimationDuration:0.3];  
    // 恆等變換. beginAnimation 和 commitAnimation 間的操作爲動畫過程  
    self.productImageView.transform = CGAffineTransformIdentity;  
    [self.productImageView setCenter:CGPointMake(self.view.frame.size.height/2, self.view.frame.size.width/2)];  
    [UIView commitAnimations];  
}  
  
//雙擊實現放大和縮小一倍  
- (void) handleDoubleTapFrom {  
    if (flag == YES) {  
        [UIView beginAnimations:nil context:nil];  
        [UIView setAnimationDuration:0.3];  
          
        [self.productImageView setFrame:CGRectMake(  
                                                   self.productImageView.frame.origin.x -self.productImageView.frame.size.width / 2,  
                                                   self.productImageView.frame.origin.y - self.productImageView.frame.size.height / 2,  
                                                   2 * self.productImageView.frame.size.width,  
                                                   2 * self.productImageView.frame.size.height)];  
        [UIView commitAnimations];  
        flag = NO;  
    }  
    else {  
        [UIView beginAnimations:nil context:nil];  
        [UIView setAnimationDuration:0.3];  
        [self.productImageView setFrame:CGRectMake(self.productImageView.frame.origin.x+self.productImageView.frame.size.width/4, self.productImageView.frame.origin.y + self.productImageView.frame.size.height/4, self.productImageView.frame.size.width/2, self.productImageView.frame.size.height/2)];  
        [UIView commitAnimations];  
        flag = YES;  
    }  
}  
特別說明這個語句:
[SingleTapGesture requireGestureRecognizerToFail:doubleTapGesture];  
有些手勢其實是互相關聯的,例如 Tap 與 LongPress、Swipe與 Pan,或是 Tap 一次與Tap 兩次。當一個 UIView 同時添加兩個相關聯的手勢時,到底我這一下手指頭按的要算是 Tap 還是 LongPress?如果照預設作法來看,只要先滿足條件的就會跳出並呼叫對應方法,舉例來說,如果同時註冊了 Pan 和 Swipe,只要手指頭一移動就會觸發 Pan 然後跳出,因而永遠都不會發生 Swipe;單點與雙點的情形也是一樣,永遠都只會觸發單點,不會有雙點。那麼這個問題有解嗎?答案是肯定的,UIGestureRecognizer 有個方法叫做requireGestureRecognizerToFail,他可以指定某一個 recognizer,即便自己已經滿足條件了,也不會立刻觸發,會等到該指定的 recognizer 確定失敗之後才觸發。
二、pinch 手勢 (捏合縮放)
說明:在模擬器中 按住alt+鼠標左鍵即可出現雙指觸摸屏幕。
//捏合縮放  
    UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchView:)];  
    [self.view addGestureRecognizer:pinchGesture];    
響應方法 (以下提供了兩種縮放響應方法)
// 處理捏合縮放手勢  
- (void) pinchView:(UIPinchGestureRecognizer *)pinchGestureRecognizer  
{  
    UIView *view = self.productImageView;  
    if (pinchGestureRecognizer.state == UIGestureRecognizerStateBegan || pinchGestureRecognizer.state == UIGestureRecognizerStateChanged) {  
        view.transform = CGAffineTransformScale(view.transform, pinchGestureRecognizer.scale, pinchGestureRecognizer.scale);  
        pinchGestureRecognizer.scale = 1;  
    }  
}  
- (void)scaleImage:(UIPinchGestureRecognizer *)recognizer   
{  
    if([recognizer state] == UIGestureRecognizerStateEnded) {  
        // 如果Pinch 手勢結束,重置 previousScale 爲 1.0  
        self.previousScale = 1.0;  
        return;  
    }  
    CGFloat newScale = [recognizer scale]-self.previousScale +1.0;  
    CGAffineTransform currentTransformation = self.productImageView.transform;  
    // CGAffineTransformScale(currentTransformation, 1, 1) 變換保持原大小  
    CGAffineTransform newTransform = CGAffineTransformScale(currentTransformation, newScale, newScale);  
    // perform the new transform  
    self.productImageView.transform = newTransform;  
    self.previousScale = [recognizer scale];  
}  
三、pan 手勢 (平移)
//平移  
   UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panView:)];  
   [panGesture setMinimumNumberOfTouches:1];  
[panGesture setMaximumNumberOfTouches:1];  
   [self.view addGestureRecognizer:panGesture];  
響應方法
// 處理拖拉手勢  
- (void) panView:(UIPanGestureRecognizer *)panGestureRecognizer  
{  
    UIView *view = self.productImageView;  
    if (panGestureRecognizer.state == UIGestureRecognizerStateBegan || panGestureRecognizer.state == UIGestureRecognizerStateChanged) {         
        CGPoint translation = [panGestureRecognizer translationInView:view.superview];          
        [view setCenter:(CGPoint){view.center.x + translation.x, view.center.y + translation.y}];         
          [panGestureRecognizer setTranslation:CGPointZero inView:view.superview];  
    }  
}  
四、rotate 手勢 (旋轉)
//旋轉  
    UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotateView:)];  
    [self.view addGestureRecognizer:rotationGesture];      
響應方法
// 處理旋轉手勢  
- (void) rotateView:(UIRotationGestureRecognizer *)rotationGestureRecognizer  
{  
    UIView *view = self.productImageView;  
    if (rotationGestureRecognizer.state == UIGestureRecognizerStateBegan || rotationGestureRecognizer.state == UIGestureRecognizerStateChanged) {         
        view.transform = CGAffineTransformRotate(view.transform, rotationGestureRecognizer.rotation);          
        [rotationGestureRecognizer setRotation:0];  
    }  
}  
最後還有一個要處理的就是模擬器的橫向擺放。
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
{  
    return ((interfaceOrientation == UIInterfaceOrientationLandscapeRight) || (interfaceOrientation == UIInterfaceOrientationLandscapeLeft));  
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章