iOS 手势UIGestureRecognizer

2024-06-06 14:32

本文主要是介绍iOS 手势UIGestureRecognizer,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!



 在 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.  }  

这篇关于iOS 手势UIGestureRecognizer的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1036376

相关文章

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

iOS剪贴板同步到Windows剪贴板(无需安装软件的方案)

摘要 剪贴板同步能够提高很多的效率,免去复制、发送、复制、粘贴的步骤,只需要在手机上复制,就可以直接在电脑上 ctrl+v 粘贴,这方面在 Apple 设备中是做的非常好的,Apple 设备之间的剪贴板同步功能(Universal Clipboard)确实非常方便,它可以在 iPhone、iPad 和 Mac 之间无缝传输剪贴板内容,从而大大提高工作效率。 但是,iPhone 如何和 Wind

iOS项目发布提交出现invalid code signing entitlements错误。

1、进入开发者账号,选择App IDs,找到自己项目对应的AppId,点击进去编辑, 2、看下错误提示出现  --Specifically, value "CVYZ6723728.*" for key "com.apple.developer.ubiquity-container-identifiers" in XX is not supported.-- 这样的错误提示 将ubiquity

我的第一次份实习工作-iOS实习生-第三个月

第三个月 这个月有一个考核项目,是一个电子书阅读器,组长说很重要,是我的实习考核项目。 我的项目XTReader,这是我参考网上的一些代码,和模仿咪咕阅读做的,功能还不完善,数据的部分是用聚合数据做的。要收费的。   还有阅读页面,基本功能实现了一下。使用了autolayout,自适应布局,也是第一次用网络,第一次用数据库,第一次用自动布局。还有很多不足。 做了一周多,有个问题一直没

我的第一次份实习工作-iOS实习生-公司使用过的软件

bittorrentsync 素材,文件同步软件 cornerstone svn 软件开发合作 mark man 测量坐标的软件 SQLLite Manager 数据库操作软件

我的第一次份实习工作-iOS实习生-第二个月

第二个月 来公司过了一个月了。每天早上9点上班,到晚上6.30下班,上下班要指纹打卡,第一个月忘了打卡好多次(),然后还要去补打卡单。公司这边还安排了,工资卡办理,招商银行卡。开了一次新员工大会,认识了公司的一些过往,公司的要求等,还加了一下公司的企业QQ,还有其他的羽毛球群,篮球群。我加了下羽毛球群,也去打了一两次。第二个月的感受,感觉跟组里面的交流跟沟通都好少,基本上还有好多人不认识。想想也

我的第一次份实习工作-iOS实习生-第一个月

实习时间:2015-08-20 到 2015-12-25  实习公司;福建天棣互联有限公司 实习岗位:iOS开发实习生 第一个月: 第一天来公司,前台报道后,人资带我去我工作的地方。到了那,就由一个组长带我,当时还没有我的办公桌,组长在第三排给我找了一个位置,擦了下桌子,把旁边的准备的电脑帮我装了下,因为学的是iOS,实习生就只能用黑苹果了,这是我实习用的电脑。 帮我装了一下电脑后,开机

iOS如何隐藏系统状态栏

这里主要说明一下iOS7系统给状态栏的适配及隐藏带来的改变。 变化一: 不隐藏状态栏的情况下,StatusBar会直接显示在当前页面上,当前页面的会延伸到 StatusBar下方,顶到最上头。 这种显示方式在iOS7上是无法改变的,也无法通过设置或者配置类达到iOS6的状态栏效果。       所以在iOS7上进行页面布局的时候要考虑

ios %.2f是四舍五入吗?

实事上这个“四舍五入”并不是数学上的“四舍五入”,而是“四舍六入五成双”,英文中被称为”round half to even”或”Banker’s rounding”。 “四舍六入五成双”是指,当保留精度的下一位不是5时,按正常的四舍五入;当保留精度的下一位是5时,如果5的后面为0则舍弃;而如果5的后面还有大于0的部分时,则无论5的前一位是奇数还是偶数,都进行进位。 1.当保留精度的下一位不是