UITouch 触摸事件处理(实例)

1. UITouch 的主要方法:iphone

C代码   收藏代码
  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;  
  5.   
  6. - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);  
  7. - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);  
  8. - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);  
 

2. 触摸时,图片移动 (实例)函数

C代码   收藏代码
  1. - (void)viewDidLoad  
  2. {  
  3.     UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(20.0, 50.0, 45.0, 45.0)];  
  4.     image.image = [UIImage imageNamed:@"baby.png"];  
  5.     image.tag = 100;  
  6.     [self.view addSubview:image];  
  7.   
  8.     [super viewDidLoad];  
  9.     // Do any additional setup after loading the view, typically from a nib.  
  10. }  
  11.   
  12. -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  
  13. {  
  14.     UITouch *touch = [touches anyObject];  
  15.     UIImageView *view1 = (UIImageView*)[self.view  viewWithTag:100];  
  16.     CGPoint point = [touch  locationInView:self.view];  
  17.     CGRect  frame = view1.frame;  
  18.     frame.origin = point;  
  19.     view1.frame = frame;  
  20. }  
 

iphone/ipad无键盘的设计是为屏幕争取更多的显示空间,大屏幕在观看图片、文字、视频等方面为用户带来了更好的用户体验。而触摸屏幕是iOS设备接受用户输入的主要方式,包括单击、双击、拨动以及多点触摸等,这些操做都会产生触摸事件。spa

 

在Cocoa中,表明触摸对象的类是UITouch。当用户触摸屏幕后,就会产生相应的事件,全部相关的UITouch对象都被包装在事件中,被程序交由特定的对象来处理。UITouch对象直接包括触摸的详细信息。设计

UITouch类中包含5个属性:orm

 

             window:触摸产生时所处的窗口。因为窗口可能发生变化,当前所在的窗口不必定是最开始的窗口。视频

             view:触摸产生时所处的视图。因为视图可能发生变化,当前视图也不必定时最初的视图。对象

             tapCount:轻击(Tap)操做和鼠标的单击操做相似,tapCount表示短期内轻击屏幕的次数。所以能够根据tapCount判断单击、双击或更多的轻击。blog

             timestamp:时间戳记录了触摸事件产生或变化时的时间。单位是秒。继承

             phase:触摸事件在屏幕上有一个周期,即触摸开始、触摸点移动、触摸结束,还有中途取消。而经过phase能够查看当前触摸事件在一个周期中所处的状态。phase是UITouchPhase类型的,这是一个枚举配型,包含了事件

·      UITouchPhaseBegan(触摸开始)

·      UITouchPhaseMoved(接触点移动)

·      UITouchPhaseStationary(接触点无移动)

·      UITouchPhaseEnded(触摸结束)

·      UITouchPhaseCancelled(触摸取消)

 

UITouch类中包含以下成员函数:

- (CGPoint)locationInView:(UIView *)view:函数返回一个CGPoint类型的值,表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置。

 

- (CGPoint)previousLocationInView:(UIView *)view:该方法记录了前一个坐标值,函数返回也是一个CGPoint类型的值, 表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置。

 

当手指接触到屏幕,不论是单点触摸仍是多点触摸,事件都会开始,直到用户全部的手指都离开屏幕。期间全部的UITouch对象都被包含在UIEvent事件对象中,由程序分发给处理者。事件记录了这个周期中全部触摸对象状态的变化。

 

只要屏幕被触摸,系统就会报若干个触摸的信息封装到UIEvent对象中发送给程序,由管理程序UIApplication对象将事件分发。通常来讲,事件将被发给主窗口,而后传给第一响应者对象(FirstResponder)处理。

 

关于响应者的概念,经过如下几点说明:

           响应者对象(Response object)

响应者对象就是能够响应事件并对事件做出处理。在iOS中,存在UIResponder类,它定义了响应者对象的全部方法。 UIApplication、UIView等类都继承了UIResponder类,UIWindow和UIKit中的控件由于继承了UIView,因此也 间接继承了UIResponder类,这些类的实例均可以看成响应者。

          第一响应者(First responder)

当前接受触摸的响应者对象被称为第一响应者,即表示当前该对象正在与用户交互,它是响应者链的开端。

           响应者链(Responder chain)

响应者链表示一系列的响应者对象。事件被交由第一响应者对象处理,若是第一响应者不处理,事件被沿着响应者链向上传递,交给下一个响应者(next responder)。通常来讲,第一响应者是个视图对象或者其子类对象,当其被触摸后事件被交由它处理,若是它不处理,事件就会被传递给它的视图控制器 对象(若是存在),而后是它的父视图(superview)对象(若是存在),以此类推,直到顶层视图。接下来会沿着顶层视图(top view)到窗口(UIWindow对象)再到程序(UIApplication对象)。若是整个过程都没有响应这个事件,该事件就被丢弃。通常状况下, 在响应者链中只要由对象处理事件,事件就中止传递。但有时候能够在视图的响应方法中根据一些条件判断来决定是否须要继续传递事件。

          管理事件分发

视图对触摸事件是否须要做处回应能够经过设置视图的userInteractionEnabled属性。默认状态为YES,若是设置为NO,能够阻 止视图接收和分发触摸事件。除此以外,当视图被隐藏(setHidden:YES)或者透明(alpha值为0)也不会收事件。不过这个属性只对视图有 效,若是想要整个程序都步响应事件,能够调用UIApplication的beginIngnoringInteractionEvents方法来彻底停 止事件接收和分发。经过endIngnoringInteractionEvents方法来恢复让程序接收和分发事件。

 

若是要让视图接收多点触摸,须要设置它的multipleTouchEnabled属性为YES,默认状态下这个属性值为NO,即视图默认不接收多点触摸。

 

首先触摸的对象是视图,而视图的类UIView继承了UIRespnder类,可是要对事件做出处理,还须要重写UIResponder类中定义的事件处理函数。根据不通的触摸状态,程序会调用相应的处理函数,这些函数包括如下几个:

            -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

            -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

            -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

            -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

 

            当手指接触屏幕时,就会调用touchesBegan:withEvent方法;

            当手指在屏幕上移时,动就会调用touchesMoved:withEvent方法;

            当手指离开屏幕时,就会调用touchesEnded:withEvent方法;

            当触摸被取消(好比触摸过程当中被来电打断),就会调用touchesCancelled:withEvent方法。而这几个方法被调用时,正好对应了UITouch类中phase属性的4个枚举值。

 

            上面的四个事件方法,在开发过程当中并不要求所有实现,能够根据须要重写特定的方法。对于这4个方法,都有两个相同的参数:NSSet类型的touches 和UIEvent类型的event。其中touches表示触摸产生的全部UITouch对象,而event表示特定的事件。由于UIEvent包含了整 个触摸过程当中全部的触摸对象,所以能够调用allTouches方法获取该事件内全部的触摸对象,也能够调用touchesForVIew:或者 touchesForWindows:取出特定视图或者窗口上的触摸对象。在这几个事件中,均可以拿到触摸对象,而后根据其位置,状态,时间属性作逻辑处 理。

 

            例如:

C代码   收藏代码
  1. -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  
  2. {  
  3.     UITouch *touch =  [touches anyObject];  
  4.     if(touch.tapCount == 2)  
  5.     {  
  6.         self.view.backgroundColor = [UIColor redColor];  
  7.     }  
  8. }  
 

            上面的例子说明在触摸手指离开后,根据tapCount点击的次数来设置当前视图的背景色。无论时一个手指仍是多个手指,轻击操做都会使每一个触摸对象的 tapCount加1,因为上面的例子不须要知道具体触摸对象的位置或时间等,所以能够直接调用touches的anyObject方法来获取任意一个触 摸对象而后判断其tapCount的值便可。

 

            检测tapCount能够放在touchesBegan也能够touchesEnded,不过通常后者跟准确,由于touchesEnded能够保证全部的手指都已经离开屏幕,这样就不会把轻击动做和按下拖动等动做混淆。

 

            轻击操做很容易引发歧义,好比当用户点了一次以后,并不知道用户是想单击仍是只是双击的一部分,或者点了两次以后并不知道用户是想双击仍是继续点击。为了解决这个问题,通常可使用“延迟调用”函数。

 

            例如:

C代码   收藏代码
  1. -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  
  2. {  
  3.     UITouch *touch =  [touches anyObject];  
  4.     if(touch.tapCount == 1)  
  5.     {  
  6.         [self performSelector:@selector(setBackground:) withObject:[UIColor blueColor] afterDelay:2];  
  7.         self.view.backgroundColor = [UIColor redColor];  
  8.     }  
  9. }  
 

            上面代码表示在第一次轻击以后,没有直接更改视图的背景属性,而是经过performSelector:withObject:afterDelay:方法设置2秒中后更改。

C代码   收藏代码
  1. -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  
  2. {  
  3.     UITouch *touch =  [touches anyObject];  
  4.     if(touch.tapCount == 2)  
  5.     {  
  6.         [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(setBackground:) object:[UIColor redColor]];  
  7.         self.view.backgroundColor = [UIColor redColor];  
  8.     }  
  9. }  
 

        双击就是两次单击的组合,所以在第一次点击的时候,设置背景色的方法已经启动,在检测到双击的时候先要把先前对应的方法取消掉,能够经过调用 NSObject类的cancelPreviousPerformRequestWithTarget:selector:object方法取消指定对象 的方法调用,而后调用双击对应的方法设置背景色为红色。

 

            下面举个例子建立能够拖动的视图,这个主要经过触摸对象的位置坐标来实现。所以调用触摸对象的locationInView:方法便可。

 

            例如:

C代码   收藏代码
  1. CGPoint originalLocation;  
  2. -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event  
  3. {  
  4.     UITouch *touch = [touches anyObject];  
  5.     originalLocation = [touch locationInView:self.view];  
  6. }  
  7.   
  8. -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event  
  9. {  
  10.     UITouch *touch = [touches anyObject];  
  11.     CGPoint currentLocation = [touch locationInView:self.view];  
  12.     CGRect frame = self.view.frame;  
  13.     frame.origin.x += currentLocation.x-originalLocation.x;  
  14.     frame.origin.y += currentLocation.y-originalLocation.y;     
  15.     self.view.frame = frame;  
  16. }  
 

            这里先在touchesBegan中经过[touch locationInView:self.view]获取手指触摸在当前视图上的位置,用CGPoint变量记录,而后在手指移动事件 touchesMoved方法中获取触摸对象当前位置,并经过于与原始位置的差值计算出移动偏移量,再设置当前视图的位置。

相关文章
相关标签/搜索