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));
}
}
藉助這些類,可以實現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));
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.