UIPanGestureRecognizer使用小結

UIPanGestureRecognizer是UIGestureRecognizer類的一個擴展類,其擴展類有UITapGestureRecognizer,UIPinchGestureRecognizer,UIRotationGestureRecognizer,UISwipeGestureRecognizer,UIPanGestureRecognizer,UILongPressGestureRecognizer。

藉助這些類,可以實現UIView對象的一些操作如對象放大縮小,移動,旋轉,滑動,輕擊等。再也不用去重寫UIView的touchBegin等方法來實現這些功能。

知識點:
UIGestureRecognizer是一個定義基本手勢的抽象類,具體什麼手勢,在以下子類中包含:
    1、拍擊UITapGestureRecognizer (任意次數的拍擊)  
    2、向裏或向外捏UIPinchGestureRecognizer (用於縮放)  
    3、搖動或者拖拽UIPanGestureRecognizer (拖動)
    4、擦碰UISwipeGestureRecognizer (以任意方向)  
    5、旋轉UIRotationGestureRecognizer (手指朝相反方向移動)  
    6、長按UILongPressGestureRecognizer (長按)

這些操作的目的都是用來修改UIView對象的frame,center,bounds屬性,還有一個Transform屬性。

我寫了一個例子,在UIView和UITableView上分別添加UIPanGestureRecognizer,實現兩個對象在手指按住對象於屏幕中拖動的效果。

聲明一個UIPanGestureRecognizer對象,添加到UIView對象上去。UIView類有這樣的方法用來動態添加和刪除UIPanGestureRecognizer對象。

UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[testPanView addGestureRecognizer:panRecognizer];

UIView管理手勢識別器的方法有:
– addGestureRecognizer:
– removeGestureRecognizer:
  gestureRecognizers  property
– gestureRecognizerShouldBegin:


我在viewDidAppear:方法中,動態添加視圖和手勢識別器。然後,實現識別器需要操作的兩個方法,用來移動視圖對象。
在這兩個方法中最終的方法是這個 CGPoint translatedPoint = [recognizer translationInView:self.view];

每一次拖動操作狀態,都會獲取到translatedPoint,從開始到結束。它是一個絕對值,可以看着在”self.view“對應的座標體系中,拖動的視圖對象center的移動開始和結束的點差。
最簡單的處理過程是這樣:
    CGPoint translatedPoint = [recognizer translationInView:self.view];
    CGFloat x = recognizer.view.center.x + translatedPoint.x;
    CGFloat y = recognizer.view.center.y + translatedPoint.y;
    recognizer.view.center = CGPointMake(x, y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];

首先獲取到移動點的值,然後算一下視圖的center值,相加一下,就得到在self.view座標體系中,視圖該移動到那個center上,一次結束就清零一次。
因爲拖動操作持續進行,所以,這個過程會持續執行。

稍微複雜點的處理過程,會捕獲到拖動開始,移動,結束等幾個狀態下的translatedPoint的值。然後做一下邏輯處理,如視圖不能溢出self.view的座標系中,如在結束時會根據方向自動滑動到某個位置。可以在handlePan2:方法中找到這些邏輯的實現代碼。

   
- (void)viewDidAppear:(BOOL)animated
{
    NSLog(@" viewDidAppear is at %@.", [NSDate date]);

    UIImage *image = [UIImage imageNamed:@"5.jpg"];

    testPanView = [[UIView alloc] initWithFrame:CGRectMake(18, 11, 100, 100)];

    UIImageView *imageview = [[UIImageView alloc] initWithFrame:[testPanView frame]];
    [imageview setImage:image];
    [testPanView addSubview:imageview];

    UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [panRecognizer setMinimumNumberOfTouches:1];
    [panRecognizer setMaximumNumberOfTouches:1];
    [panRecognizer setDelegate:self];
    [testPanView addGestureRecognizer:panRecognizer];

    [self.view addSubview:testPanView];

    testPanTableView = [[UITableView alloc] initWithFrame:CGRectMake(118, 121, 100, 100) style:UITableViewStylePlain];

    UIPanGestureRecognizer *panRecognizer2 = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan2:)];
    [panRecognizer2 setMinimumNumberOfTouches:1];
    [panRecognizer2 setMaximumNumberOfTouches:1];
    [panRecognizer2 setDelegate:self];
    [testPanTableView addGestureRecognizer:panRecognizer2];

    [self.view addSubview:testPanTableView];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    CGPoint translatedPoint = [recognizer translationInView:self.view];
    NSLog(@"gesture translatedPoint  is %@", NSStringFromCGPoint(translatedPoint));
    CGFloat x = recognizer.view.center.x + translatedPoint.x;
    CGFloat y = recognizer.view.center.y + translatedPoint.y;

    recognizer.view.center = CGPointMake(x, y);

    NSLog(@"pan gesture testPanView moving  is %@,%@", NSStringFromCGPoint(recognizer.view.center), NSStringFromCGRect(recognizer.view.frame));

    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}



- (void)handlePan2:(UIPanGestureRecognizer *)recognizer
{
    // NSLog(@"gesture translatedPoint  xxoo xxoo");
    CGPoint translatedPoint = [recognizer translationInView:self.view];

    if ([(UIPanGestureRecognizer *)recognizer state] == UIGestureRecognizerStateBegan) {
        firstX = recognizer.view.center.x;
        firstY = recognizer.view.center.y;
        NSLog(@"self.view bounds is %@", NSStringFromCGRect(self.view.bounds));
        NSLog(@"pan gesture testPanView begin  is %@,%@", NSStringFromCGPoint([recognizer view].center), NSStringFromCGRect([recognizer view].frame));
    }

    if ([(UIPanGestureRecognizer *)recognizer state] == UIGestureRecognizerStateChanged) {
        CGFloat x = firstX + translatedPoint.x;
        CGFloat y = firstX + translatedPoint.y;

        if (x < recognizer.view.width / 2.0) {
            x = recognizer.view.width / 2.0;
        } else if (x + recognizer.view.width / 2.0 > self.view.width) {
            x = self.view.width - recognizer.view.width / 2.0;
        }

        if (y < recognizer.view.height / 2.0) {
            y = recognizer.view.height / 2.0;
        } else if (y + recognizer.view.height / 2.0 > self.view.height) {
            y = self.view.height - recognizer.view.height / 2.0;
        }

        NSLog(@"gesture translatedPoint moving  is %@", NSStringFromCGPoint(translatedPoint));

        recognizer.view.center = CGPointMake(x, y);
    }

    if (([(UIPanGestureRecognizer *)recognizer state] == UIGestureRecognizerStateEnded) || ([(UIPanGestureRecognizer *)recognizer state] == UIGestureRecognizerStateCancelled)) {
        CGFloat x = recognizer.view.center.x;
        CGFloat y = recognizer.view.center.y;

        if (x > firstX) {
            x = self.view.width - recognizer.view.width / 2.0;
        } else {
            x = recognizer.view.width / 2.0;
        }

        if (y > firstY) {
            y = self.view.height - recognizer.view.height / 2.0;
        } else {
            y = recognizer.view.height / 2.0;
        }

        CGFloat velocityX = (0.2 *[recognizer velocityInView:self.view].x);

        [UIView beginAnimations:nil context:NULL];

        [UIView setAnimationDuration:ABS(velocityX * 0.00002 + 0.2)];

        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

        recognizer.view.center = CGPointMake(x, y);

        [UIView commitAnimations];

        NSLog(@"gesture translatedPoint  end is %@", NSStringFromCGPoint(translatedPoint));

        NSLog(@"pan gesture testPanView end  is %@,%@", NSStringFromCGPoint([recognizer view].center), NSStringFromCGRect([recognizer view].frame));
    }
}

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