UIGestureRecognizer与UIMenuController

UIGestureRecognizer对象会截取本应由视图处理的触摸事件。当某个UIGestureRecognizer对象识别出特定的手势后,就会向指定的对象发送指定的消息。
 在为应用添加手势识别功能时,需要针对特定的手势创建相应的UIGestureRecognizer子类对象,而不是直接使用UIGestureRecognizer对象。
 使用UIGestureRecognizer子类对象时,除了要设置目标动作对,还要将该子类对象“附着”在某个视图上。当该子类对象根据当前附着的视图所发生的触摸事件识别出相应的手势时,就会向指定的目标对象发送指定的动作消息。由UIGestureRecognizer对象发出的动作消息都会遵守以下规范:

-(void)action:(UIGestureRecognizer*)gestureRecognizer;

UIGestureRecognizer对象在识别手势时,会截取本应由其附着的视图自行处理的触摸事件。附着了UIGestureRecognizer对象的视图可能不会收到常规的UIResponder消息,例如touchesBegan:withEvent:。

UIGestureRecognizer对象会截取UITouch对象

由于UIGestureRecognizer对象会通过截取触摸事件来识别手势,因此,在UIGestureRecognizer对象识别出手势之前,UIView会收到所有UIResponder消息。对于UITapGestureRecognizer来说,在识别出点击手势(在屏幕中的一小块区域触摸并迅速抬起手指)之前,UIView会收到touchesBegan:withEvent:消息;在识别出点击手势之后,UITapGestureRecognizer会自行处理相关触摸事件,由这些触摸事件所引发的UIResponder消息将不会再发送给UIView。直到UITapGestureRecognizer检测出点击手势已经结束,UIView才会重新收到UIResponder消息(touchesCancelled:withEvent:)。

//延迟touchesBegan的接收
 double  TapRecognizer.delaysTouchesBegan=YES;

如果需要为视图添加多种手势,就需要考虑这些手势之间的关系。双击手势包含两次单击,为了避免UITapGestureRecognizer将双击事件分拆为两个单击事件,可以设置UITapGestureRecognizer在单击后暂时不进行识别,直到确定不是双击手势后再识别为单击手势。

 [tapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
UIMenuController

UIMenuController对象可以包含一组UIMenuItem对象(菜单项),并能在现有的视图上显示这些UIMenuItem对象。
每个iOS应用只有一个UIMenuController对象。当应用要显示该对象时,要先为它设置一组UIMenuItem对象,然后设置显示位置(矩形区域),最后将其设置为可见。
要显示UIMenuController对象,还要满足一个条件:显示UIMenuController对象的UIView对象必须是当前UIWindow对象的第一响应对象。
这是因为该对象在显示前会枚举所有的UIMenuItem对象,检查第一响应对象是否实现了指定的动作方法。如果没有实现该方法,UIMenuController对象就不会显示相应的UIMenuItem对象;如果所有UIMenuItem对象的动作方法都没有实现,应用就不会显示UIMenuController对象。
如果要将某个自定义的UIView子类对象设置为第一响应对象,就必须覆盖该对象的canBecomeFirstResponder方法。

-(BOOL)canBecomeFirstResponder
{
    return YES;
}

显示前会枚举所有的UIMenuItem对象,检查第一响应对象是否实现了指定的动作方法。如果没有实现该方法,UIMenuController对象就不会显示相应的UIMenuItem对象;如果所有UIMenuItem对象的动作方法都没有实现,应用就不会显示UIMenuController对象。
  当某个UIGestureRecognizer子类对象触发特定的事件后,其state属性会发生变化。以UILongPressGestureRecognizer对象为例,和上述三种事件相对应的state属性分别为:UIGestureRecognizerStatePossible、UIGestureRecognizerStateBegan和UIGestureRecognizerStateEnded。
  当某个UIGestureRecognizer子类对象的state属性发生变化时(除了切换至UIGestureRecognizerStatePossible的情况),该对象就会向其目标对象发送指定的动作消息。所以当某个长按手势开始和结束时,相应的UILongPressGestureRecognizer对象都会向其目标对象发送同一个消息。和该消息匹配的方法可以通过UIGestureRecognizer对象的state属性来判断当前的事件类型,然后根据不同的事件类型执行不同的代码。
  通常情况下,UIGestureRecognizer对象不会将其处理过的触摸事件再交给其他对象来处理。一旦某个UIGestureRecognizer子类对象识别出了相应的手势,就会“吃掉”所有相关的触摸事件,导致其他UIGestureRecognizer对象没有机会再处理这些触摸事件。对TouchTracker,这种特性会导致BNRDrawView对象无法处理拖动手势,这是因为整个拖动手势都是在长按手势中发生的。要解决这个问题,需要让UILongPressGestureRecognizer对象和UIPanGestureRecognizer对象能够同时识别手势。
  UIGestureRecognizerDelegate协议声明了很多方法,gestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizer:(如下代码)。当某个UIGestureRecognizer子类对象识别出特定的手势后,如果发现其他的UIGestureRecognizer子类对象也识别出了特定的手势,就会向其委托对象发送gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:消息。如果相应的方法返回YES,那么当前的UIGestureRecognizer子类对象就会和其他UIGestureRecognizer子类对象共享UITouch对象。

-(BOOL)gestureRecognizer: (UIGestureRecognizer*) gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)other
{
    if(gestureRecognizer==self.moveRecognizer)
    {
        return YES;
        
    }
        return NO;
}
//将当前手指的位置设置为初始手势的位置
[gr setTranslation:CGPointZero inView:self];

现UIPanGestureRecognizer对象的动作方法moveLine:。在moveLine:中,要调用UIPanGestureRecognizer对象的translationInView:方法。该方法会根据传入的UIView对象的坐标系,以CGPoint结构的形式返回手指的拖动距离。当拖动手势开始时,拖动距离是0点(x和y都是0)。拖动的过程中,拖动距离会不断发生变化(将手指移动至窗口的最右端,x的值就会很高。将手指移回手势的起始位置,拖动距离就会变回0点)。
  当UIGestureRecognizer对象的cancelsTouchesInView属性为NO时,这个对象所依附的UIView对象仍然会收到相应的UIResponder消息,从而有机会处理相关的UITouch对象。

UIMenuController与UIResponderStandardEditActions

如果某个UIResponder子类需要实现特定的“编辑”功能,就可以实现相应的方法。以UITextField为例,为了能够剪切当前选中的文字,UITextField实现了cut:方法。UIResponderStandardEditActions协议声明了所有这类“编辑”方法。
  如果某个UIView子类实现了UIResponderStandardEditActions协议中的方法,那么当这个子类对象显示UIMenuController对象时,就会出现和这些方法相对应的菜单项。这是因为该对象会在显示前枚举所有的“编辑”菜单项,然后根据其动作消息向视图发送canPerformAction:withSender:消息。如果视图实现了指定的方法,该消息就会返回YES,否则返回NO。UIMenuController对象会根据canPerformAction:withSender:的返回结果判断是否应该显示相应的菜单项。

-(BOOL)canPerformAction:(SEL) actionwithSender:(id)sender  
{  
if(action == @selector(copy:)) 
{
  returnNO;
}
 //父类的实现会根据目标对象是否实现了特定的动作方法,返回YES或NO 
 return  [super  canPerformAction:action  withSender:sender];
}
再谈UIGestureRecognizer

13.8

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容