iOS_触摸事件与手势识别
2015-10-09 20:17
399 查看
目 录:
一、触摸事件
1.1iOS的输入事件
1.2 触摸事件的处理
1.3 UITouch类中包含五个属性
1.4 UITouch类中包含两个成员函数
1.5响应者链
二、手势识别
2.1使用手势处理器(UIGestureRecognizer)
2.2案例分析
1.1 iOS的输入事件
在iOS中事件分为三类:
1.触摸事件:通过触摸、手势进行触发(例如手指点击、缩放)
2.运动事件:通过加速器进行触发(例如手机晃动)
3.远程控制事件:通过其他远程设备触发(例如耳机控制按钮)
下图是苹果官方对于这三种事件的形象描述:
![](http://images2015.cnblogs.com/blog/757139/201510/757139-20151008210049065-1655741907.png)
iOS中许多事件对象都是UIEvent类的实例,UIEvent记录了事件所产生的时刻和事件类型。通过UIEvent对象的type属性可以获取事件的类型。在iOS中不是任何对象都能处理事件,只有继承了UIResponser的对象才能接收并处理事件。我们称之为“响应者对象”。UIApplication,UIViewController,UIView都继承自UIResponser,因此它们都是响应者对象,都能够接收并处理事件。
UIEvent类对事件类型定义了enum常量:
typedefNS_ENUM(NSInteger,UIEventType)
{
UIEventTypeTouches,
UIEventTypeMotion,
UIEventTypeRemoteControl,
};
在以下三种情况下,不能接收事件
1.与用户交互的属性设为NO
2.hideen设为YES(隐藏)
3.alpha=0(透明)
1.2 触摸事件的处理
UIView是UIResponder的子类,可以覆盖下列4个方法处理不同的触摸事件。
1. 一根或者多根手指开始触摸屏幕
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
2.一根或者多根手指在屏幕上移动(随着手指的移动,会持续调用该方法)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
3.一根或者多根手指离开屏幕
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
4.触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
注意:所有UIKit控件均继承自UIView
上述4个方法都有个UIEvent的参数,通过UIEvent可以得到事件的类型和产生时间,以及当前处于活动状态的所有触摸操作。但是,通常会使用UITouch对象而不是UIEvent对象来处理触摸事件。当用户触摸屏幕时,系统会创建一个UITouch实例,并将该对象和接触屏幕的那根手指关联。UITouch保存着手指在屏幕上触摸的位置。当手指移动时,系统会更新同一个UITouch对象,使之能够一直保存该手指在屏幕上的当前位置。当手指离开屏幕时,系统会取消相应的UITouch对象。另外,UITouch对象还会保存一些其他信息,比如,手指的前一个位置、手指按下屏幕的次数(tapCount, 可以用来判断单击和双击事件)。
提示:iPhone开发中,要避免使用双击事件
1.3 UITouch类中包含五个属性
window:触摸产生时所处的窗口。由于窗口可能发生变化,当前所在的窗口不一定是最开始的窗口
view:触摸产生时所处的视图。由于视图可能发生变化,当前视图也不一定时最初的视图
tapCount:点按操作和鼠标的单击操作类似,tapCount表示短时间内点按屏幕的次数。因此可以根据tapCount判断单击、双击或更多的点按
timestamp:时间戳记录了触摸事件产生或变化时的时间,单位是秒
phase:触摸事件在屏幕上有一个周期,即触摸开始、触摸点移动、触摸结束,还有中途取消。通过phase可以查看当前触摸事件在一个周期中所处的状态。phase是UITouchPhase类型的,是一个枚举配型,包含:
- UITouchPhaseBegan(触摸开始)
- UITouchPhaseMoved(接触点移动)
- UITouchPhaseStationary(接触点无移动)
- UITouchPhaseEnded(触摸结束)
- UITouchPhaseCancelled(触摸取消)
1.4 UITouch类中包含两个成员函数
1) - (CGPoint)locationInView:(UIView *)view:
返回一个CGPoint类型的值,表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置
2) - (CGPoint)previousLocationInView:(UIView *)view:
该方法记录了前一个坐标值,函数返回也是一个CGPoint类型的值, 表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置
1.5响应者链
我们知道在iOS程序中无论是最后面的UIWindow还是最前面的某个按钮,它们的摆放是有前后关系的,一个控件可以放到另一个控件上面或下面,那么用户点击某个控件时是触发上面的控件还是下面的控件呢,这种先后关系构成一个链条就叫“响应者链”。在iOS中响应者链的关系可以用下图表示:
![](http://images2015.cnblogs.com/blog/757139/201510/757139-20151008212147424-64000749.png)
通常来说,第一响应者都是UIView控件或UIView子类控件,当用户触摸该控件后,事件最先由该控件本身处理;如果该控件自身不处理事件,事件就会被传播到它对应的视图控制器(如果存在);如果该控制器不处理该事件,事件就会传播到包含该控件的父UIView控件(如果存在);如果该父UIView控件不处理该事件,事件就会传播到父UIView控件对应的视图控制器(如果存在).......直到顶层视图对应的视图控制器。
如果事件从第一响应者开始传播,一直传播到应用界面的顶层视图的视图控制器,该事件依然没有得到处理,接下来该事件就会传播到应用程序窗口(UIWindow也继承了UIView)对象;如果应用程序窗口也不处理该事件,该事件就会传播到UIApplication(它也继承了UIResponder);如果该UIApplication还不处理该事件,该事件就会传播到应用程序委托对象(使用Xcode的项目模板生成的所有iOS项目中的应用程序委托类都继承了UIResponder)。
事件响应者链的典型传播路线如下:
First Responder -> First Responder的视图控制器(如果有)-> 父容器(如果有)->父容器的视图控制器(如果有) ->UIWindow -> UIApplication -> 应用程序委托对象
案例1:触摸事件响应
二、手势识别
2.1使用手势处理器(UIGestureRecognizer)
2.1.1基础知识介绍
通过手势处理器处理用户触碰事件更加简单,而且无论处理哪种触碰手势,都可面向UIGestureRecognizer编程,UIGestureRecognizer提供了如下子类:
2.1.2使用手势处理器处理用户触碰手势的编程步骤
1.根据程序要处理的手势创建对应的手势处理器对象。创建手势处理器需要指定target和action参数—当该控件上发生触碰手势后,该target对象的action方法就会被触发。
2.如果该UI控件不允许用户交互,则该UI控件的userInteractionEnabled属性设为YES;如果希望该控件可支持多点触碰,还需要将multipleTouchEnabled设为YES;
3.调用UI控件的addGestureRecognizer:方法添加手势处理器。
UIGestureRecognizer作为所有手势处理器的基类,它提供了如下常用的方法和属性。
- locationInView:(UIView*)view :返回该手势在view控件中的触碰位置。
- locationOfTouch:(NSInteger)touchIndex inView:(UIView*)view : 返回该手势中地touchIndex个触碰点在view控件中的触碰位置。
- numberOfTouches: 返回该手势包含触碰点的数量(也就是用户用了几个手指进行触碰)。
- view:返回激发该手势的UI控件。
- enabled:用户设置和返回该手势处理器是否可用
- state:获取该手势所处的状态,比如手势刚开始时处于UIGestureRecognizerStateBegan状态,手势结束时处于UIGestureRecognizerStateEnded状态。
2.2案例分析
2.2.1使用UITapGestureRecognizer处理点击手势
UITapGestureRecognizer还提供了如下两个属性。
numberOfTapsRequired:指定了该手势处理器只处理几次触碰事件。
numberOfTouchesRequired:指定该手势处理器只处理几个手指的触碰事件。
案例代码如下:
2.2.2使用UIPinchGestureRecognizer处理捏合手势
UIPinchGestureRecognizer定义了如下两个属性来获取捏合相关信息。
- scale:获取捏合的比例。
- velocity:获取捏合的速度。
案例代码如下:
2.2.3使用UIRotationGestureRecognizer处理旋转手势
使用UIRotationGestureRecognizer处理旋转手势的步骤与其他手势处理器的步骤完全相同。UIRotationGestureRecognizer定义了如下两个属性来获取旋转相关的信息。
- roration :获取旋转角度。
- velocity:获取旋转速度。
2.2.4使用UISwipeGestureRecognizer处理轻扫手势
使用UISwipeGestureRecognizer处理轻扫手势的步骤与其他手势处理器的步骤完全相同。UISwipeGestureRecognizer定义了如下两个属性来获取旋转相关的信息。
- direction:设置该手势处理器处理该方向的轻扫。
- numberOfTouchesRequired:指定该手势处理器只处理几个手指的触碰事件。
2.2.5使用UIPanGestureRecognizer处理拖动手势
使用UIPanGestureRecognizer处理轻扫手势的步骤与其他手势处理器的步骤完全相同。UIPanGestureRecognizer定义了如下两个属性来获取旋转相关的信息。
- maximumNumberOfTouches:设置该拖动手势处理器最多支持几个手指拖动。
- minimumNumeberOfTouches:设置该拖动手势处理器最少需要几个手指一起拖动。
除此之外,该手势处理器还提供了如下方法来获取拖动相关信息。
- translationView:获取该拖动手势在指定控件上的位移。该方法返回一个CGPoint结构体数据,该结构体中x变量的值代表了水平方向的位移,y变量的值代表了垂直方向的位移。
- velocityInView:获取该拖动手势在指定控件上的拖动速度。该方法返回一个CGPoint结构体数据,该结构体中x变量的值代表了水平方向的速度,y变量的值代表了垂直方向的速度。
2.2.6使用UILongPressGestureRecognizer处理长按手势
使用UILongPressGestureRecognizer处理轻扫手势的步骤与其他手势处理器的步骤完全相同。UILongPressGestureRecognizer定义了如下属性来获取旋转相关的信息。
- minimumPressDuration:指定用户至少在屏幕上按下多少秒才会触发该长按手势。该属性默认值为0.5。
- numberOfTouchesRequired:指定必须使用几个手指在屏幕上长按才会触发手势。
- allowableMovement:指定该长按手势允许用户移动手指的最大距离。如果用户手指按下时移动超过了该距离。则长按手指失效。
知识扩充:UIView的常用方法
1.convertRect:fromView:
转换一个矩形从其他视图坐标系到接收者坐标系。
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view
参数 :
rect :一个在视图坐标系中的矩形
view :一个视图内部有矩形在他的坐标系中。如果视图是nil,那么这个方法将会基于窗口来转换。否则视图和接收者必须都属于同一个UIWindow对象
返回值 :The converted rectangle 转换过的矩形
2.convertRect:toView:
转换接收者坐标系中的矩形到其他视图
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view
参数 :
rect :一个在接收者坐标系中的矩形
view :要转换过去的目标视图对象。如果这个是视图是nil,这个方法将会基于窗口坐标系来转换。否者视图和接收者必须属于同一个UIwindow对象
返回值 :一个转换过的矩形
3.convertPoint:fromView:
把一个点从一个坐标系转换到接收者的坐标系
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view
参数 :
point :一个视图中坐标系上的点
view :一个视图包含了点和他自身坐标系。如果是图是nil,那么这个方法将尝试转换基于窗口的坐标系。否则视图和那个接收者必须属于同一个UIWindow对象。
返回值 :一个转换到接收者坐标系的点
4.convertPoint:toView:
转换一个点从接收者坐标系到给定的视图坐标系
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
参数:
point :一个在调用者坐标系中的点
view :一个包含了需要被转换的点的视图。如果视图是nil,那么这个方法将会转换成基于窗口的坐标。否则视图和接收者都要属于同一个UIWindow对象。
返回值 :基于视图的坐标系转换过的点
示例:
//1.将点的坐标转换成btn的坐标系
CGPoint newPoint = [self convertPoint:point toView:btn];
5.hitTest:withEvent:
返回接收者视图层次中最远的派生(包括它本身)的特定的点。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
参数 :
point :接收者坐标系中的点
event :触发这个方法的事件或者是如果这个方法被预调用就返回nil
返回值 :一个视图对象最远的派生点。如果这个点位于接收者之外就返回nil
示例:
//不做任何处理,按照默认的响应链顺序
return [super hitTest:point withEvent:event];
讨论:
这个方法贯穿视图的层次发送pointInside:withEvent: 消息到每一个子视图用来决定那个子视图需要接收触摸事件。如果pointInside:withEvent: 返回YES,那么视图的层次全部贯穿;否则视图层次的分支是被否定的。你不太需要调用这个方法,但是你需要重写它用来隐藏子视图的触摸事件。 如果视图是隐藏的,禁止用户交互的或者透明值小于01那么这个方法不可用。
一、触摸事件
1.1iOS的输入事件
1.2 触摸事件的处理
1.3 UITouch类中包含五个属性
1.4 UITouch类中包含两个成员函数
1.5响应者链
二、手势识别
2.1使用手势处理器(UIGestureRecognizer)
2.2案例分析
1.1 iOS的输入事件
在iOS中事件分为三类:
1.触摸事件:通过触摸、手势进行触发(例如手指点击、缩放)
2.运动事件:通过加速器进行触发(例如手机晃动)
3.远程控制事件:通过其他远程设备触发(例如耳机控制按钮)
下图是苹果官方对于这三种事件的形象描述:
![](http://images2015.cnblogs.com/blog/757139/201510/757139-20151008210049065-1655741907.png)
iOS中许多事件对象都是UIEvent类的实例,UIEvent记录了事件所产生的时刻和事件类型。通过UIEvent对象的type属性可以获取事件的类型。在iOS中不是任何对象都能处理事件,只有继承了UIResponser的对象才能接收并处理事件。我们称之为“响应者对象”。UIApplication,UIViewController,UIView都继承自UIResponser,因此它们都是响应者对象,都能够接收并处理事件。
UIEvent类对事件类型定义了enum常量:
typedefNS_ENUM(NSInteger,UIEventType)
{
UIEventTypeTouches,
UIEventTypeMotion,
UIEventTypeRemoteControl,
};
在以下三种情况下,不能接收事件
1.与用户交互的属性设为NO
2.hideen设为YES(隐藏)
3.alpha=0(透明)
1.2 触摸事件的处理
UIView是UIResponder的子类,可以覆盖下列4个方法处理不同的触摸事件。
1. 一根或者多根手指开始触摸屏幕
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
2.一根或者多根手指在屏幕上移动(随着手指的移动,会持续调用该方法)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
3.一根或者多根手指离开屏幕
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
4.触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
注意:所有UIKit控件均继承自UIView
上述4个方法都有个UIEvent的参数,通过UIEvent可以得到事件的类型和产生时间,以及当前处于活动状态的所有触摸操作。但是,通常会使用UITouch对象而不是UIEvent对象来处理触摸事件。当用户触摸屏幕时,系统会创建一个UITouch实例,并将该对象和接触屏幕的那根手指关联。UITouch保存着手指在屏幕上触摸的位置。当手指移动时,系统会更新同一个UITouch对象,使之能够一直保存该手指在屏幕上的当前位置。当手指离开屏幕时,系统会取消相应的UITouch对象。另外,UITouch对象还会保存一些其他信息,比如,手指的前一个位置、手指按下屏幕的次数(tapCount, 可以用来判断单击和双击事件)。
提示:iPhone开发中,要避免使用双击事件
1.3 UITouch类中包含五个属性
window:触摸产生时所处的窗口。由于窗口可能发生变化,当前所在的窗口不一定是最开始的窗口
view:触摸产生时所处的视图。由于视图可能发生变化,当前视图也不一定时最初的视图
tapCount:点按操作和鼠标的单击操作类似,tapCount表示短时间内点按屏幕的次数。因此可以根据tapCount判断单击、双击或更多的点按
timestamp:时间戳记录了触摸事件产生或变化时的时间,单位是秒
phase:触摸事件在屏幕上有一个周期,即触摸开始、触摸点移动、触摸结束,还有中途取消。通过phase可以查看当前触摸事件在一个周期中所处的状态。phase是UITouchPhase类型的,是一个枚举配型,包含:
- UITouchPhaseBegan(触摸开始)
- UITouchPhaseMoved(接触点移动)
- UITouchPhaseStationary(接触点无移动)
- UITouchPhaseEnded(触摸结束)
- UITouchPhaseCancelled(触摸取消)
1.4 UITouch类中包含两个成员函数
1) - (CGPoint)locationInView:(UIView *)view:
返回一个CGPoint类型的值,表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置
2) - (CGPoint)previousLocationInView:(UIView *)view:
该方法记录了前一个坐标值,函数返回也是一个CGPoint类型的值, 表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置
1.5响应者链
我们知道在iOS程序中无论是最后面的UIWindow还是最前面的某个按钮,它们的摆放是有前后关系的,一个控件可以放到另一个控件上面或下面,那么用户点击某个控件时是触发上面的控件还是下面的控件呢,这种先后关系构成一个链条就叫“响应者链”。在iOS中响应者链的关系可以用下图表示:
![](http://images2015.cnblogs.com/blog/757139/201510/757139-20151008212147424-64000749.png)
通常来说,第一响应者都是UIView控件或UIView子类控件,当用户触摸该控件后,事件最先由该控件本身处理;如果该控件自身不处理事件,事件就会被传播到它对应的视图控制器(如果存在);如果该控制器不处理该事件,事件就会传播到包含该控件的父UIView控件(如果存在);如果该父UIView控件不处理该事件,事件就会传播到父UIView控件对应的视图控制器(如果存在).......直到顶层视图对应的视图控制器。
如果事件从第一响应者开始传播,一直传播到应用界面的顶层视图的视图控制器,该事件依然没有得到处理,接下来该事件就会传播到应用程序窗口(UIWindow也继承了UIView)对象;如果应用程序窗口也不处理该事件,该事件就会传播到UIApplication(它也继承了UIResponder);如果该UIApplication还不处理该事件,该事件就会传播到应用程序委托对象(使用Xcode的项目模板生成的所有iOS项目中的应用程序委托类都继承了UIResponder)。
事件响应者链的典型传播路线如下:
First Responder -> First Responder的视图控制器(如果有)-> 父容器(如果有)->父容器的视图控制器(如果有) ->UIWindow -> UIApplication -> 应用程序委托对象
案例1:触摸事件响应
#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //支持多点触摸 self.view.multipleTouchEnabled = YES; //接受用户触摸交互 self.view.userInteractionEnabled = YES; } //当用户手指开始接触控件或窗口事件时激发该方法 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* 知识点补充: 1.当某个UIView发生触摸事件时,系统会将和事件相关的UITouch对象作为参数传入 2.因为可以有多根手指同时触发同一个事件,所以传给视图的是一组UITouch对象,保存在NSSet中,例如: 1)如果两根手指同时触摸某个视图,那么touchesBegan:withEvent:的第一个参数是包含两个UITouch实例的NSSet对象; 2)如果这两根手指一前一后分开触摸同一个视图,那么视图会收到两个独立的touchesBegan:withEvent:消息,并且每个NSSet对象中只包含一个UITouch对象 因此,根据NSSet中UITouch的个数可以判断出是单点触摸还是多点触摸 */ NSLog(@"触摸点击"); //通过读取touches创建新的UITouch对象 UITouch *touch = [touches anyObject]; //取出当前点击的坐标点 CGPoint location = [touch locationInView:self.view]; //取出上一个坐标点(适用于移动情况下,如果只是纯粹的两次触摸点击,无效果) CGPoint previousLocation = [touch previousLocationInView:self.view]; //打印输出坐标点 NSLog(@"%@,%@",NSStringFromCGPoint(location),NSStringFromCGPoint(previousLocation)); //输出所有的UITouch对象 // NSLog(@"%@",[touches allObjects]); } //当用户手指结束触摸控件时激发该方法 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"触摸结束"); } //当用户手指在控件上移动时激发该方法 -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"触摸移动"); } //当系统事件(比如内存低事件)中止了触碰事件时激发该方法 -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"取消触摸"); } @end
二、手势识别
2.1使用手势处理器(UIGestureRecognizer)
2.1.1基础知识介绍
通过手势处理器处理用户触碰事件更加简单,而且无论处理哪种触碰手势,都可面向UIGestureRecognizer编程,UIGestureRecognizer提供了如下子类:
UITapGestureRecognizer | 点按手势 |
UIPinchGestureRecognizer | 捏合手势 |
UIPanGestureRecognizer | 拖动手势 |
UISwipeGestureRecognizer | 轻扫手势(滑动手势),支持四个方向的轻扫,但是不同的方向要分别定义轻扫手势 |
UIRotationGestureRecognizer | 旋转手势 |
UILongPressGestureRecognizer | 长按手势 |
1.根据程序要处理的手势创建对应的手势处理器对象。创建手势处理器需要指定target和action参数—当该控件上发生触碰手势后,该target对象的action方法就会被触发。
2.如果该UI控件不允许用户交互,则该UI控件的userInteractionEnabled属性设为YES;如果希望该控件可支持多点触碰,还需要将multipleTouchEnabled设为YES;
3.调用UI控件的addGestureRecognizer:方法添加手势处理器。
UIGestureRecognizer作为所有手势处理器的基类,它提供了如下常用的方法和属性。
- locationInView:(UIView*)view :返回该手势在view控件中的触碰位置。
- locationOfTouch:(NSInteger)touchIndex inView:(UIView*)view : 返回该手势中地touchIndex个触碰点在view控件中的触碰位置。
- numberOfTouches: 返回该手势包含触碰点的数量(也就是用户用了几个手指进行触碰)。
- view:返回激发该手势的UI控件。
- enabled:用户设置和返回该手势处理器是否可用
- state:获取该手势所处的状态,比如手势刚开始时处于UIGestureRecognizerStateBegan状态,手势结束时处于UIGestureRecognizerStateEnded状态。
2.2案例分析
2.2.1使用UITapGestureRecognizer处理点击手势
UITapGestureRecognizer还提供了如下两个属性。
numberOfTapsRequired:指定了该手势处理器只处理几次触碰事件。
numberOfTouchesRequired:指定该手势处理器只处理几个手指的触碰事件。
案例代码如下:
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIView *myView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //设置myView控件支持用户交互 self.myView.userInteractionEnabled = YES; //设置myView控件支持多点触碰 self.myView.multipleTouchEnabled = YES; //一、tap手势 //创建手势处理器,指定使用该控制器的tap:方法处理手势 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)]; //指定该手势处理器只处理几次触碰事件 tap.numberOfTapsRequired = 1; //指定该手势处理器只处理几个手指的触碰事件 tap.numberOfTouchesRequired = 2; //为myView控件添加手势处理器 [self.myView addGestureRecognizer:tap]; } //实现手势处理器的方法,该方法应该声明一个形参 //当该方法被激发时,手势处理器会作为参数传给该方法的参数 -(void)tap:(UITapGestureRecognizer *)sender { UIView *view = sender.view; if ([sender.view.backgroundColor isEqual:[UIColor redColor]]) { view.backgroundColor = [UIColor greenColor]; } else { view.backgroundColor = [UIColor redColor]; } } @end
2.2.2使用UIPinchGestureRecognizer处理捏合手势
UIPinchGestureRecognizer定义了如下两个属性来获取捏合相关信息。
- scale:获取捏合的比例。
- velocity:获取捏合的速度。
案例代码如下:
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIView *myView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //设置myView控件支持用户交互 self.myView.userInteractionEnabled = YES; //设置myView控件支持多点触碰 self.myView.multipleTouchEnabled = YES; //二、pinch手势(放大、缩小)(捏合) UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)]; [self.view addGestureRecognizer:pinch]; } //实现手势处理器的方法,该方法应该声明一个形参 //当该方法被激发时,手势处理器会作为参数传给该方法的参数 -(void)pinch:(UIPinchGestureRecognizer *)sender { if (sender.state == UIGestureRecognizerStateRecognized) { //1.使用仿射变换获取当前的状态 CGAffineTransform transform = self.myView.transform; //2.按照变换系数对view进行变换 transform = CGAffineTransformScale(transform, sender.scale, sender.scale); //3.按照新的仿射变换进行变换视图 self.myView.transform = transform; } } @end
2.2.3使用UIRotationGestureRecognizer处理旋转手势
使用UIRotationGestureRecognizer处理旋转手势的步骤与其他手势处理器的步骤完全相同。UIRotationGestureRecognizer定义了如下两个属性来获取旋转相关的信息。
- roration :获取旋转角度。
- velocity:获取旋转速度。
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIView *myView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //设置myView控件支持用户交互 self.myView.userInteractionEnabled = YES; //设置myView控件支持多点触碰 self.myView.multipleTouchEnabled = YES; //三、Rotain手势(旋转) UIRotationGestureRecognizer *rotain = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotain:)]; //给view控件添加手势处理器 [self.view addGestureRecognizer:rotain]; } -(void)rotain:(UIRotationGestureRecognizer *)sender { if (sender.state == UIGestureRecognizerStateChanged) { //方式一: //使用放射变换进行旋转 // self.myView.transform = CGAffineTransformMakeRotation(sender.rotation); //方式二: //1.使用仿射变换获取当前的状态 CGAffineTransform transform = self.myView.transform; //2.按照变换系数对view进行变换 transform = CGAffineTransformRotate(transform, sender.rotation); //3.按照新的仿射变换进行变换视图 self.myView.transform = transform; } sender.rotation = 0; /* 方式一与方式二的区别在于: 在执行之后方式一不需要进行复位操作,方式二需要进行复位。以防影响下一次操作。 注意:复位不是必须的,可以根据开发者的需要进行选择是否需要进行复位操作。 */ } @end
2.2.4使用UISwipeGestureRecognizer处理轻扫手势
使用UISwipeGestureRecognizer处理轻扫手势的步骤与其他手势处理器的步骤完全相同。UISwipeGestureRecognizer定义了如下两个属性来获取旋转相关的信息。
- direction:设置该手势处理器处理该方向的轻扫。
- numberOfTouchesRequired:指定该手势处理器只处理几个手指的触碰事件。
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIView *myView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //设置myView控件支持用户交互 self.myView.userInteractionEnabled = YES; //设置myView控件支持多点触碰 self.myView.multipleTouchEnabled = YES; //六、swipe手势(轻扫) UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)]; // swipe.direction = UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionLeft; [self.view addGestureRecognizer:swipe]; } -(void)swipe:(UISwipeGestureRecognizer *)sender { if (sender.direction == UISwipeGestureRecognizerDirectionRight) { NSLog(@"swipe right"); } else if (sender.direction == UISwipeGestureRecognizerDirectionLeft) { NSLog(@"swipe left"); } else if (sender.direction == UISwipeGestureRecognizerDirectionUp) { NSLog(@"swipe up"); } else if (sender.direction == UISwipeGestureRecognizerDirectionDown) { NSLog(@"swipe down"); } } @end
2.2.5使用UIPanGestureRecognizer处理拖动手势
使用UIPanGestureRecognizer处理轻扫手势的步骤与其他手势处理器的步骤完全相同。UIPanGestureRecognizer定义了如下两个属性来获取旋转相关的信息。
- maximumNumberOfTouches:设置该拖动手势处理器最多支持几个手指拖动。
- minimumNumeberOfTouches:设置该拖动手势处理器最少需要几个手指一起拖动。
除此之外,该手势处理器还提供了如下方法来获取拖动相关信息。
- translationView:获取该拖动手势在指定控件上的位移。该方法返回一个CGPoint结构体数据,该结构体中x变量的值代表了水平方向的位移,y变量的值代表了垂直方向的位移。
- velocityInView:获取该拖动手势在指定控件上的拖动速度。该方法返回一个CGPoint结构体数据,该结构体中x变量的值代表了水平方向的速度,y变量的值代表了垂直方向的速度。
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIView *myView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //设置myView控件支持用户交互 self.myView.userInteractionEnabled = YES; //设置myView控件支持多点触碰 self.myView.multipleTouchEnabled = YES; //四、pan手势(拖动) UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)]; //指定该手势处理器处理的最小手指数 pan.minimumNumberOfTouches = 1; //指定该手势处理器处理的最da手指数 pan.maximumNumberOfTouches = 1; [self.myView addGestureRecognizer:pan]; } -(void)pan:(UIPanGestureRecognizer *)sender { //判断手势的状态 if (sender.state == UIGestureRecognizerStateChanged) { CGPoint offSetPoint = [sender translationInView:self.view]; CGPoint center = self.myView.center; self.myView.center = CGPointMake(center.x+offSetPoint.x, center.y+offSetPoint.y); // CGPoint velocity = [sender velocityInView:self.myView]; // CGPoint translation = [sender translationInView:self.myView]; // NSLog(@"%@,%@",velocity,translation); } //进行复位操作 [sender setTranslation:CGPointZero inView:self.view]; } @end
2.2.6使用UILongPressGestureRecognizer处理长按手势
使用UILongPressGestureRecognizer处理轻扫手势的步骤与其他手势处理器的步骤完全相同。UILongPressGestureRecognizer定义了如下属性来获取旋转相关的信息。
- minimumPressDuration:指定用户至少在屏幕上按下多少秒才会触发该长按手势。该属性默认值为0.5。
- numberOfTouchesRequired:指定必须使用几个手指在屏幕上长按才会触发手势。
- allowableMovement:指定该长按手势允许用户移动手指的最大距离。如果用户手指按下时移动超过了该距离。则长按手指失效。
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIView *myView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //设置myView控件支持用户交互 self.myView.userInteractionEnabled = YES; //设置myView控件支持多点触碰 self.myView.multipleTouchEnabled = YES; //五、longPress手势(长按) UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)]; //指定该手势处理器只处理几个手指的触碰事件 longPress.numberOfTouchesRequired = 1; //长按的持续时间(按住多久之后才算做是长按) longPress.minimumPressDuration = 0.5f; //为控件添加长按手势 [self.myView addGestureRecognizer:longPress]; } -(void)longPress:(UILongPressGestureRecognizer *)sender { if (sender.state == UIGestureRecognizerStateChanged) { self.myView.backgroundColor = [UIColor yellowColor]; } else if (sender.state == UIGestureRecognizerStateEnded) { self.myView.backgroundColor = [UIColor redColor]; } } @end
知识扩充:UIView的常用方法
1.convertRect:fromView:
转换一个矩形从其他视图坐标系到接收者坐标系。
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view
参数 :
rect :一个在视图坐标系中的矩形
view :一个视图内部有矩形在他的坐标系中。如果视图是nil,那么这个方法将会基于窗口来转换。否则视图和接收者必须都属于同一个UIWindow对象
返回值 :The converted rectangle 转换过的矩形
2.convertRect:toView:
转换接收者坐标系中的矩形到其他视图
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view
参数 :
rect :一个在接收者坐标系中的矩形
view :要转换过去的目标视图对象。如果这个是视图是nil,这个方法将会基于窗口坐标系来转换。否者视图和接收者必须属于同一个UIwindow对象
返回值 :一个转换过的矩形
3.convertPoint:fromView:
把一个点从一个坐标系转换到接收者的坐标系
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view
参数 :
point :一个视图中坐标系上的点
view :一个视图包含了点和他自身坐标系。如果是图是nil,那么这个方法将尝试转换基于窗口的坐标系。否则视图和那个接收者必须属于同一个UIWindow对象。
返回值 :一个转换到接收者坐标系的点
4.convertPoint:toView:
转换一个点从接收者坐标系到给定的视图坐标系
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
参数:
point :一个在调用者坐标系中的点
view :一个包含了需要被转换的点的视图。如果视图是nil,那么这个方法将会转换成基于窗口的坐标。否则视图和接收者都要属于同一个UIWindow对象。
返回值 :基于视图的坐标系转换过的点
示例:
//1.将点的坐标转换成btn的坐标系
CGPoint newPoint = [self convertPoint:point toView:btn];
5.hitTest:withEvent:
返回接收者视图层次中最远的派生(包括它本身)的特定的点。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
参数 :
point :接收者坐标系中的点
event :触发这个方法的事件或者是如果这个方法被预调用就返回nil
返回值 :一个视图对象最远的派生点。如果这个点位于接收者之外就返回nil
示例:
//不做任何处理,按照默认的响应链顺序
return [super hitTest:point withEvent:event];
讨论:
这个方法贯穿视图的层次发送pointInside:withEvent: 消息到每一个子视图用来决定那个子视图需要接收触摸事件。如果pointInside:withEvent: 返回YES,那么视图的层次全部贯穿;否则视图层次的分支是被否定的。你不太需要调用这个方法,但是你需要重写它用来隐藏子视图的触摸事件。 如果视图是隐藏的,禁止用户交互的或者透明值小于01那么这个方法不可用。
相关文章推荐
- GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助
- nios ii avalon结构中的按键中断如何配置!
- iOS大典之Core Data
- 【iOS】本地推送和模拟远程推送
- iOS中的GCD(1)---串、并行队列和同、异步添加
- ios之viewWithTag
- NIOS II IDE编译出错:no file name for '-include'。Quartus ii中的.tcl文件run不起来
- iOS 禁止横屏
- iOS 地图与定位
- iOS SDK
- ios深度解析之coreData
- IOS开发:动画1
- 我的IOS学习历程-第二天
- IOS开发:动画2 AlayerAnimation
- iOS地图系统导航
- IOS Xib使用——Xib表示局部界面
- iOS图片拉伸技巧
- iOS开发--应用国际化,应用内切换语言
- CAShapeLayer绘画圆环,圆环进度条
- 苹果开发者账号注册、申请续费整个流程