iOS 手势UIGestureRecognizer

来源:互联网 发布:3dmax导入unity3d 编辑:程序博客网 时间:2024/04/28 04:27


 在 iPhone 或 iPad 的开发中,除了用 touchesBegan / touchesMoved / touchesEnded 这组方法来控制使用者的手指触控外,也可以用 UIGestureRecognizer 的衍生类別来进行判断。用 UIGestureRecognizer 的好处在于有现成的手势,开发者不用自己计算手指移动轨迹。UIGestureRecognizer的衍生类別有以下几种:


UITapGestureRecognizer
UIPinchGestureRecognizer
UIRotationGestureRecognizer
UISwipeGestureRecognizer
UIPanGestureRecognizer
UILongPressGestureRecognizer


从命名上不难了解這些类別所对应代表的手势,分別是 Tap(点一下)、Pinch(二指往內或往外拨动)、Rotation(旋转)、Swipe(滑动,快速移动)、Pan (拖移,慢速移动)以及 LongPress(长按)。這些手势別在使用上也很简单,只要在使用前定义并添加到对应的视图上即可。


复制代码
// 定义一个 recognizer, 并加到需要偵測该手势的 UIView 元件上
- (void)viewDidLoad {
UISwipeGestureRecognizer* recognizer;
// handleSwipeFrom 是偵測到手势,所要呼叫的方法
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:selfaction:@selector(handleSwipeFrom)];
// 不同的 Recognizer 有不同的实体变数
// 例如 SwipeGesture 可以指定方向
// 而 TapGesture 則可以指定次數
recognizer.direction = UISwipeGestureRecognizerDirectionUp
[self.view addGestureRecognizer:recognizer];
[recognizer release];
}


- (void)handleSwipeFrom:(UISwipeGestureRecognizer*)recognizer {
// 触发手勢事件后,在这里作些事情


// 底下是刪除手势的方法
[self.view removeGestureRecognizer:recognizer];
}
复制代码
问题來了。有些手势其实是互相关联的,例如 Tap 与 LongPress、Swipe与 Pan,或是 Tap 一次与Tap 兩次。当一個 UIView 同时添加兩个相关联的手势时,到底我这一下手指头按的要算是 Tap 还是 LongPress?如果照預设作法来看,只要「先滿足条件」的就会跳出并呼叫对应方法,举例来说,如果同时注册了 Pan 和 Swipe,只要手指头一移动就会触发 Pan 然后跳出,因而永远都不會发生 Swipe;单点与双点的情形也是一样,永远都只会触发单点,不會有双点。


那么这个问题有解吗?答案是肯定的,UIGestureRecognizer 有个方法叫做requireGestureRecognizerToFail,他可以指定某一个 recognizer,即便自己已经滿足條件了,也不會立刻触发,会等到该指定的 recognizer 确定失败之后才触发。以同时支持单点与双点的手势为例,代码如下:


复制代码
- (void)viewDidLoad {
// 单击的 Recognizer
UITapGestureRecognizer* singleRecognizer;
singleRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(handleSingleTapFrom)];
singleTapRecognizer.numberOfTapsRequired = 1; // 单击
[self.view addGestureRecognizer:singleRecognizer];


// 双击的 Recognizer
UITapGestureRecognizer* double;
doubleRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(handleDoubleTapFrom)];
doubleTapRecognizer.numberOfTapsRequired = 2; // 双击
[self.view addGestureRecognizer:doubleRecognizer];


// 关键在这一行,如果双击确定偵測失败才會触发单击
[singleRecognizer requireGestureRecognizerToFail:doubleRecognizer];
[singleRecognizer release];
[doubleRecognizer release];

Demo
首先新建一个基于Sigle view Application的项目,名为GestureTest;我的项目结构如下:






往viewController.xib文件里拖动一个imageView,并使覆盖整个屏幕,改动属性为:






viewController.h文件:


 


 


1.     #import <UIKit/UIKit.h>  


2.       


3.     @interface ViewController : UIViewController{  


4.         IBOutlet UIImageView *imageView;  


5.     }  


6.     @property (nonatomic,retain)IBOutlet UIImageView *imageView;  


7.     @end  


并使xib文件里的imageView与之连接;


 


然后是viewController.m文件的实现部分:


 


 


1.     @synthesize imageView;  


2.       


3.     CGFloat lastScaleFactor=1;//放大、缩小  


4.     CGFloat  netRotation;//旋转  


5.     CGPoint netTranslation;//平衡  


6.     NSArray *images;//图片数组  


7.     int imageIndex=0;//数组下标  


8.       


9.     - (void)viewDidLoad  


10.   {  


11.       //1、创建手势实例,并连接方法handleTapGesture,点击手势  


12.       UITapGestureRecognizer *tapGesture=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTapGesture:)];  


13.       //设置手势点击数,双击:点2下  


14.       tapGesture.numberOfTapsRequired=2;  


15.       // imageView添加手势识别  


16.       [imageView addGestureRecognizer:tapGesture];  


17.       //释放内存  


18.       [tapGesture release];  


19.         


20.       //2、手势为捏的姿势:按住option按钮配合鼠标来做这个动作在虚拟器上  


21.       UIPinchGestureRecognizer *pinchGesture=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinchGesture:)];  


22.       [imageView addGestureRecognizer:pinchGesture];//imageView添加手势识别  


23.       [pinchGesture release];  


24.         


25.       //3、旋转手势:按住option按钮配合鼠标来做这个动作在虚拟器上  


26.       UIRotationGestureRecognizer *rotateGesture=[[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(handleRotateGesture:)];  


27.       [imageView addGestureRecognizer:rotateGesture];  


28.       [rotateGesture release];  


29.         


30.       //4、拖手势  


31.       UIPanGestureRecognizer *panGesture=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanGesture:)];  


32.      // [imageView addGestureRecognizer:panGesture];  


33.       [panGesture release];  


34.         


35.       //5、划动手势  


36.       images=[[NSArray alloc]initWithObjects:@"cell.jpg",@"heihua.jpg",@"xuanyi.jpg", nil];  


37.       //右划  


38.       UISwipeGestureRecognizer *swipeGesture=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeGesture:)];  


39.       [imageView addGestureRecognizer:swipeGesture];  


40.       [swipeGesture release];  


41.       //左划  


42.       UISwipeGestureRecognizer *swipeLeftGesture=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeGesture:)];  


43.       swipeGesture.direction=UISwipeGestureRecognizerDirectionLeft;//不设置黑夜是右  


44.       [imageView addGestureRecognizer:swipeLeftGesture];  


45.       [swipeLeftGesture release];  


46.         


47.       //6、长按手势  


48.       UILongPressGestureRecognizer *longpressGesutre=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleLongpressGesture:)];  


49.       //长按时间为1秒  


50.       longpressGesutre.minimumPressDuration=1;  


51.       //允许15秒中运动  


52.       longpressGesutre.allowableMovement=15;  


53.       //所需触摸1次  


54.       longpressGesutre.numberOfTouchesRequired=1;  


55.       [imageView addGestureRecognizer:longpressGesutre];  


56.       [longpressGesutre release];  


57.         


58.       [super viewDidLoad];  


59.       // Do any additional setup after loading the view, typically from a nib.  


60.   }  


61.   //双击屏幕时会调用此方法,放大和缩小图片  


62.   -(IBAction)handleTapGesture:(UIGestureRecognizer*)sender{  


63.       //判断imageView的内容模式是否是UIViewContentModeScaleAspectFit,该模式是原比例,按照图片原时比例显示大小  


64.       if(sender.view.contentMode==UIViewContentModeScaleAspectFit){  


65.           //把imageView模式改成UIViewContentModeCenter,按照图片原先的大小显示中心的一部分在imageView  


66.           sender.view.contentMode=UIViewContentModeCenter;  


67.       }else{  


68.           sender.view.contentMode=UIViewContentModeScaleAspectFit;  


69.       }  


70.   }  


71.   //捏的手势,使图片放大和缩小,捏的动作是一个连续的动作  


72.   -(IBAction)handlePinchGesture:(UIGestureRecognizer*)sender{  


73.       //得到sender捏手势的大小  


74.       CGFloat factor=[(UIPinchGestureRecognizer*)sender scale];  


75.       if(factor>1){  


76.           //图片放大  


77.           sender.view.transform=CGAffineTransformMakeScale(lastScaleFactor+(factor-1), (lastScaleFactor+(factor-1)));  


78.                                                              


79.       }else{  


80.           //缩小  


81.           sender.view.transform=CGAffineTransformMakeScale(lastScaleFactor*factor, lastScaleFactor*factor);  


82.                                                              


83.       }  


84.       //状态是否结束,如果结束保存数据  


85.       if(sender.state==UIGestureRecognizerStateEnded){  


86.           if(factor>1){  


87.               lastScaleFactor+=(factor-1);  


88.           }else{  


89.               lastScaleFactor*=factor;  


90.           }  


91.       }  


92.   }  


93.   //旋转手势  


94.   -(IBAction)handleRotateGesture:(UIGestureRecognizer*)sender{  


95.       //浮点类型,得到sender的旋转度数  


96.       CGFloat rotation=[(UIRotationGestureRecognizer*)sender rotation];  


97.       //旋转角度CGAffineTransformMakeRotation  


98.       CGAffineTransform transform=CGAffineTransformMakeRotation(rotation+netRotation);  


99.       //改变图像角度  


100.      sender.view.transform=transform;  


101.      //状态结束,保存数据  


102.      if(sender.state==UIGestureRecognizerStateEnded){  


103.          netRotation+=rotation;  


104.      }  


105.         


106.  }  


107.  //拖手势  


108.  -(IBAction)handlePanGesture:(UIGestureRecognizer*)sender{  


109.      //得到拖的过程中的xy坐标  


110.      CGPoint translation=[(UIPanGestureRecognizer*)sender translationInView:imageView];  


111.      //平移图片CGAffineTransformMakeTranslation  


112.      sender.view.transform=CGAffineTransformMakeTranslation(netTranslation.x+translation.x, netTranslation.y+translation.y);  


113.      //状态结束,保存数据  


114.      if(sender.state==UIGestureRecognizerStateEnded){  


115.          netTranslation.x+=translation.x;  


116.          netTranslation.y+=translation.y;  


117.      }  


118.        


119.  }  


120.  //划动手势  


121.  -(IBAction)handleSwipeGesture:(UIGestureRecognizer*)sender{  


122.      //划动的方向  


123.      UISwipeGestureRecognizerDirection direction=[(UISwipeGestureRecognizer*) sender direction];  


124.      //判断是上下左右  


125.      switch (direction) {  


126.          case UISwipeGestureRecognizerDirectionUp:  


127.              NSLog(@"up");  


128.              break;  


129.          case UISwipeGestureRecognizerDirectionDown:  


130.              NSLog(@"down");  


131.              break;  


132.          case UISwipeGestureRecognizerDirectionLeft:  


133.              NSLog(@"left");  


134.              imageIndex++;//下标++  


135.              break;  


136.          case UISwipeGestureRecognizerDirectionRight:  


137.              NSLog(@"right");  


138.              imageIndex--;//下标--  


139.              break;  


140.          default:  


141.              break;  


142.      }  


143.      //得到不越界不<0的下标  


144.      imageIndex=(imageIndex<0)?([images count]-1):imageIndex%[images count];  


145.      //imageView显示图片  


146.      imageView.image=[UIImage imageNamed:[images objectAtIndex:imageIndex]];  


147.        


148.  }  


149.  //长按手势  


150.  -(IBAction)handleLongpressGesture:(UIGestureRecognizer*)sender{  


151.      //创建警告  


152.      UIActionSheet *actionSheet=[[UIActionSheet alloc]initWithTitle:@"Image options" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:@"Save Image",@"Copy", nil];  


153.      //当前view显示警告  


154.      [actionSheet showInView:self.view];  


155.      [actionSheet release];  


156.  }  


157.  -(void)dealloc{  


158.      [images release];  


159.      [imageView release];  


160.      [super dealloc];  


161.  }  
0 0