一.Gesture Recognizers

Gesture Recognizers是在iOS3.2引入的,可以用来识别手势、简化定制视图事件处理的对象。Gesture Recognizers的基类为UIGestureRecognizer,这一个抽象基类,定义了实现底层手势识别行为的编程接口。在UIKit框架中提供了6个具体的手势识别类,用来识别常见的手势。这6个手势识别器类为:

为了识别手势,需要将Gesture Recognizers关联到其检测触摸事件的view上,可以使用UIViewaddGestureRecognizer:方法将手势识别器绑定到视图上。Gesture Recognizers在触摸事件处理流程中,处于观察者的角色,其不是view层级结构的一部分,所以也不参与responder chain。在将触摸事件发送给hit-test view之前,系统会先将触摸事件发送到hit-test view上绑定的或hit-test view父视图(superview)上绑定的Gesture Recognizers上。其流程大概如下图所示: 注:图中view与Gesture Recognizer的关系是,Gesture Recognizer关联在view或view的superview(可能多级)上。

二.Gesture Recognizers与事件分发路径的关系

Gesture Recognizers可能会延迟将触摸事件发送到hit-test view上,默认情况下,当Gesture Recognizers识别到手势后,会向hit-test view发送cancel消息,来取消之前发给hit-test view的事件。控制这个流程的是UIGestureRecognizer的三个属性

  • cancelsTouchesInView (默认为YES)
  • delaysTouchesBegan (默认为NO)
  • delaysTouchesEnded (默认为YES)
  • cancelsTouchesInView为YES,表示当Gesture Recognizers识别到手势后,会向hit-test view发送 touchesCancelled:withEvent:消息来取消hit-test view对此触摸序列的处理,这样只有Gesture Recognizers能响应此触摸序列,hit-test view不再响应。如果为NO,则不发送touchesCancelled:withEvent:消息给hit-test view,这样会使Gesture Recognizers和hit-test view同时响应触摸序列。

  • delaysTouchesBegan为NO,表示触摸序列开始时,而手势识别器还未识别出此手势时,touch事件会同时发向hit-test view,这样在手势识别器还未识别出此手势,hit-test view同时也可以收到同样的触摸事件。如果为YES,则在手势识别器在识别手势的过程中,不会有任何触摸事件发送给hit-test view,如果手势识别器最终识别到了手势,则也不会发送任何消息(包括touchesCancelled:withEvent:)给hit-test view;若干手势识别最终没有识别到手势,则所有的触摸事件在发给hit-test view处理。关于这个特性,可参考UIScrollViewdelaysContentTouches属性。这样属性也谨慎使用,使用不当会导致UI无响应。

  • delaysTouchesEnded,在文档上的解释是,当手势识别器在识别手势时,对于UITouchPhaseEnded阶段的touch会延迟发送给hit-test view,在手势识别成功后,发送给hit-test view cancel消息,手势识别失败时,发送原来的end消息。其给出了了这样的例子识别双击操作的UITapGestureRecognizer对象,其numberOfTapsRequired设为2,在用户进行双击操作时,如果delaysTouchesEnded为NO,则hit-test view中的调用序列为 touchesBegan:withEvent:, touchesEnded:withEvent:, touchesBegan:withEvent:, and touchesCancelled:withEvent: 如果delaysTouchesEnded为YES,则调用序列为: touchesBegan:withEvent:, touchesBegan:withEvent:, touchesCancelled:withEvent:, touchesCancelled:withEvent: 但我在实际测试时,并非如此,实际测试的结果是,如果delaysTouchesEnded为NO,则调用序列为: touchesBegan:withEvent:, touchesEnded:withEvent:, TapGestureRecognizer 检测到双击

    如果delaysTouchesEnded为YES,则调用序列为: touchesBegan:withEvent:, touchesEnded:withEvent:, TapGestureRecognizer 检测到双击 touchesCancelled:withEvent: 这个问题还没搞清楚!

    三.多个Gesture Recognizer之间的关系

    在一个view上可以绑定多个Gesture Recognizer,在默认情况下,触摸序列中的触摸事件会以不确定的次序在各个gesture recognizer中传递,直到事件最终发送给hit-test view(如果中间没被Gesture Recognizer识别出并截获的话)。多个Gesture Recognizer之间的关系也可以根据需要定制,主要有下面几种行为

    1.使其中一个gesture recognizer失败的情况下,另一个gesture recognizer才能分析事件。

    以同时识别单击操作和双击操作为例,两个gesture recognizers分别用来识别单击和双击,分别为singleTapGesture和doubleTapGesture。在默认情况下,当用户进行单击操作时,singleTapGesture会识别出一个单击操作,doubleTapGesture也会识别出一个双击动作,但我们的意图是,这仅仅是一个双击操作。在这种情况下我们可以使用UIGestureRecognizer的requireGestureRecognizerToFail:方法来使singleTapGesture在doubleTapGesture识别识别的时候才分析事件,如果doubleTapGesture识别出双击事件,则singleTapGesture不会有任何动作。

    [singleTapGesture requireGestureRecognizerToFail:doubleTapGesture];

    需要注意的是,在这种情况下,如果用户进行单击操作,需要一段延时(即doubleTapGesture识别失败),singleTapGesture才会识别出单击动作,进行单击处理,这段时间很多,对实际使用几乎没有影响。

    2.精确控制gesture recognizer是否响应某个事件或事件序列.

    UIGestureRecognizerDelegate协议中有两个可选方法可以控制gesture recognizer是否需要识别某些事件

    • gestureRecognizerShouldBegin: 此方法在gesture recognizer视图转出UIGestureRecognizerStatePossible状态时调用,如果返回NO,则转换到UIGestureRecognizerStateFailed;如果返回YES,则继续识别触摸序列.(默认情况下为YES)
    • gestureRecognizer:shouldReceiveTouch: 此方法在window对象在有触摸事件发生时,调用gesture recognizer的touchesBegan:withEvent:方法之前调用,如果返回NO,则gesture recognizer不会看到此触摸事件。(默认情况下为YES).

    另外,在UIGestureRecognizer类中也有两个可以重写的方法来完成与Delegate方法中相同的功能 - (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer; - (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer;

    3.允许多个手势识别器共同识别

    默认情况下,两个gesture recognizers不会同时识别它们的手势,但是你可以实现UIGestureRecognizerDelegate协议中的 gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:方法对其进行控制。这个方法在这两个gesture recognizers中的任意一个将block另一个的触摸事件时调用,如果返回YES,则两个gesture recognizers可同时识别,如果返回NO,则并不保证两个gesture recognizers必不能同时识别,因为另外一个gesture recognizer的此方法可能返回YES。也就是说两个gesture recognizers的delegate方法只要任意一个返回YES,则这两个就可以同时识别;只有两个都返回NO的时候,才是互斥的。默认情况下是返回NO。

    有这样一个例子,如果要侦测在window上的所有触摸事件,可以将gesture recognizer关联到window上,默认情况下如果手势被window识别,则子视图中的gesture recognizer就失效了,而我们在window上的gesture recognizer的目的只是监控所有事件,但并不处理这些事件,具体事件的处理还需要子视图中的各个gesture recognizer去处理,这样我们可以实现window上绑定gesture recognizer的delegate方法,使gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:返回YES即可。

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
    }

    四.UIScrollView的类似行为

    scroll view没有滚动栏,当在scroll view上有触摸行为时其要识别出触摸行为的目的是scroll view本身还是其内容子视图。定制scrollview如何处理这种情况,看查看UIScrollView类的下列属性和方法。 – touchesShouldBegin:withEvent:inContentView: – touchesShouldCancelInContentView: canCancelContentTouches delaysContentTouches

    参考: Event Handling Guide for iOS – Gesture Recognizers UIGestureRecognizer Class Reference UIGestureRecognizerDelegate Protocol Reference Detecting all touches in an app UIScrollView Class Reference How to recognize swipe gesture in UIScrollView UIGestureRecognizer blocks subview for handling touch events UIButton touch is delayed when in UIScrollView Why is scrolling a UITableView much more responsive than scrolling a UIScrollView? How to cancel touches exactly like UIScrollView?

本文转载至 http://blog.csdn.net/namehzf/article/details/7424882

1.一个View有GestureRecognizer又有按钮(或其它需要处理action event的控件)时,有时按钮不灵敏,解决办法: 
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 
     CGPoint pt      = [touch locationInView:baseView]; 
     UIView *btn     = [baseView viewWithTag:TAG_MYBTN]; 
     CGPoint ptInbtn = [baseView convertPoint:pt toView:btn]; 
     return ![btn pointInside:ptInbtn withEvent:nil]; 
  
2.实现某个view点一下就移除时,要防止移除两次。(此方法适用于希望GestureRecognizer只执行一次的情况) 
-(void)OnTapViewTobeRemoved:(UITapGestureRecognizer *)sender 
     if (!sender.enabled) { 
           return; 
     } 
     sender.enabled = NO; 
     [sender.view removeFromSuperview]; 
 
 
做的APP需要在一个UIWebView中随点击位置动态出现button,用touchesBegan等怎么调试都不行,普通的UIView就可以,找了半天终于知道UIWebView不能这样用,那么怎么做呢,只有用UITapGestureRecognizer替代了,其他的手势还可以用UIPinchGestureRecognizer(放大缩小)和UIPanGestureRecognizer(拖动),SO,我们现在以UITagGestureRecongnizer来做,获取webView中的位置。

UITapGestureRecognizer* myTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(handleSingleTap:)];
[self.view
addGestureRecognizer:singleTap]; //这个可以加到任何控件上,比如你只想响应WebView,我正好填满整个屏幕

myTap.delegate = self;
myTap.cancelsTouchesInView = NO;
[myTap
release];

如果是双击可以这样:
    UITapGestureRecognizer *doubleTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(doubleTap:)]; 
    doubleTap.numberOfTouchesRequired = 2;

[self.theWebView addGestureRecognizer:doubleTap];

然后有一个关键的,要实现一个方法:

- (BOOL)gestureRecognizer:(UIGestureRecognizer
*)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer
*)otherGestureRecognizer
{
    return YES;
}

最后,响应的方法中,可以获取点击的坐标哦!

-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
    CGPoint
gesturePoint = [sender locationInView:self.view];
   
NSLog(@"handleSingleTap!gesturePoint:%f,y:%f",gesturePoint.x,gesturePoint.y);

}

UIGestureRecognizer学习笔记的更多相关文章

  1. UIGestureRecognizer学习笔记2

    The concrete subclasses of UIGestureRecognizer are the following: UITapGestureRecognizer UIPinchGest ...

  2. iOS学习笔记--触摸事件

    最近空闲时间在学习iOS相关知识,几周没有更新文章了,今天总结下这些天的学习内容,也整理下iOS的学习笔记,以便以后查阅翻看- iOS中的事件可以分为3大类型: 触摸事件 加速计事件 远程控制事件 响 ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  5. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  6. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  7. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  8. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  9. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

随机推荐

  1. python学习笔记(19)--PTVS的安装

    说明: 1. 折腾了两天eclipse,pydev,好不容易都弄好了,发现不会建工程,建完工程打不开,老是提示工作空间里有隐藏文件什么的,网上查了说是把.project里面的name标签的名字改了就行 ...

  2. 利用IT++搭建通信仿真平台

    IT++ is a C++ library of mathematical, signal processing and communication classes and functions.也就是 ...

  3. flume sourcetype avro http

    flume  当sourcetype=http的时候可以用 curl -X POST -d '[{"headers" :{"APPSTORE" : " ...

  4. linux大小写转换

    [root@ob2 mytmp]# cat aa2.txt|sed 's#[a-z]#\u&#g'ETH0      LINK ENCAP:ETHERNET  HWADDR 00:0C:29: ...

  5. iOS边练边学--定时任务和HUD

    九宫格计算思路 利用控件的索引index计算出控件所在的行号和列号 利用列号计算控件的x值 利用行号计算控件的y值 HUD 其他说法:指示器.遮盖.蒙板 半透明HUD的做法 背景色设置为半透明颜色 定 ...

  6. js学习笔记12----json数据格式,语法,遍历

    1.json数据格式:var json={} 示例一: var user = {'name':'sese','age':'24','sex':'女'} console.log(user.age); / ...

  7. 数据库 Oracle数据库性能优化

    --在Oacle数据库涉及到全表扫描的SQL查询(top,count)中, --现场用户删除表中大部分数据,只保留1W条数据,但是查询仍然很慢,检查磁盘IO,发现磁盘IO不是很高 --经过分析Oacl ...

  8. rar安装和使用

    参考:http://blog.csdn.net/dracotianlong/article/details/18011033 .下载rar wget http://www.rarlab.com/rar ...

  9. e577. Enabling Antialiasing

    // See e575 The Quintessential Drawing Program public void paint(Graphics g) { // Retrieve the graph ...

  10. linux -- ubuntu 通过命令行,设置文件及其子文件的权限

    想一次修改某个目录下所有文件的权限,包括子目录中的文件权限也要修改,要使用参数-R表示启动递归处理. 例如: [root@localhost ~]# chmod 777 /home/user 注:仅把 ...