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)); }}