UIWebView下各种手势识别器的协作处理方案

 前置阅读:

1. iOS私有API(二) UIGestureRecognizerDelegate的两个函数

2. iOS私有API(三) UIWebView下的手势识别器gestureRecognizer

UIWebView下有很多的手势,它是怎么管理的呢?主要是两种途径:自管理和委托,即

1. 继承自UIGestureRecognizer或其子类,重载以下两个函数

// same behavior as the equivalent delegate methods, but can be used by subclasses to define class-wide prevention rules
// for example, a UITapGestureRecognizer never prevents another UITapGestureRecognizer with a higher tap count
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer;
- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer; 

2. 通过UIGestureRecognizerDelegate,当中还有non-public API。

这里只讨论由UIWebBrowserView和UIWebDocumentView管理的手势。其它assistant所管理的手势,他们的手势的delegate都是各自的assistant,不需要UIWebBrowserView去操心。不过这些assistant和UIWebBrowserView之间都是互相引用的关系,即assistant有成员变量保存UIWebBrowserView的实例指针,究竟assistant在处理手势时让UIWebBrowserView帮了什么忙,这个有空再研究了。

UIWebBrowserView只管理一个手势UIWebTouchEventsGestureRecognizer。这个手势很强势,重载了 canBePreventedByGestureRecognizer 函数,永远返回NO,即不会被任何手势阻止。实际上,TouchEvents手势在其state未变成began之前,就会调用一下delegate(UIWebBrowserView)的action,此时UIWebBrowserView查询到UIWebTouchEventsGestureRecognizer仍是possible
state,会做一些清理上次操作的工作。在这个预处理之前,TouchEvents手势已经向内核WebCore查询过是否有js的preventDefault要求了,并把这个信息作为成员变量保存着,故这次的预处理如果发现preventDefault=true,还会做些额外的操作。

UIWebDocumentView是UIWebBrowserView的父类,管理6个手势

UITapGestureRecognizer *_singleTapGestureRecognizer;
UITapGestureRecognizer *_doubleTapGestureRecognizer;
UITapGestureRecognizer *_twoFingerDoubleTapGestureRecognizer;
UILongPressGestureRecognizer *_highlightLongPressGestureRecognizer;
UILongPressGestureRecognizer *_longPressGestureRecognizer;
UIPanGestureRecognizer *_twoFingerPanGestureRecognizer; 

而且UIGestureRecognizerDelegate这个protocol是由UIWebDocumentView实现的,确切来说,是由UIWebDocumentView(Interaction)这个category来做的。

我们来看看UIWebDocumentView如何实现UIGestureRecognizerDelegate。

1. - (BOOL)_gestureRecognizer:(id)arg1 shouldReceiveTouch:(id)arg2;

如果arg1为两个doubleTap之一时,返回YES,即双击操作始终接收touch;如果是其它手势,再检测一下这个touch是否点在了插件view上(插件包括:音视频、MapKitView、iAd),如果是,则不接收这个touch。

2. - (BOOL)_gestureRecognizer:(id)arg1 canPreventGestureRecognizer:(id)arg2;

BOOL result = YES;
    if (m_highlightRecognizer == gestureRecognizer || m_longPressRecognizer == gestureRecognizer)
    {
        Class cls = [UIScrollViewPanGestureRecognizer class];
        result = [otherGestureRecognizer isKindOfClass:cls] == NO;
    }
    return result; 

3. - (BOOL)_gestureRecognizer:(id)arg1 canBePreventedByGestureRecognizer:(id)arg2;

有两种情况返回YES:

情况1:如果arg2不是UITextInteractionAssistant.loupeGesture && arg2不是UIWebSelectionAssistant所管理的1.5次点击手势或长按手势

情况2:arg1不是UIWebDocumentView管理的两个longPress手势

4. - (BOOL)_gestureRecognizer:(id)arg1 shouldRecognizeSimultaneouslyWithGestureRecognizer:(id)arg2;

BOOL result = NO;
    if ((arg1 == m_highlightRecognizer && arg2 == m_longPressRecognizer)
        || (arg2 == m_highlightRecognizer && arg1 == m_longPressRecognizer)
        || (_singleTaparg1 == arg1 && _textSelectionAssistant.singleTapGesture == arg2)
        || (_textSelectionAssistant.singleTapGesture == arg1 && _singleTaparg1 == arg2))
    {
        result = YES;
    }
    return result; 

5. - (BOOL)_gestureRecognizerShouldBegin:(id)arg1;

这个的实现最复杂,需要根据当前touch的位置做各种判断,会使用线程锁进入内核WebCore做查询。进入这个回调时,手势已经接收到足够的touch信息,所以在此回调中去询问手势识别器实例的各个状态时,除了state外都已是对的了。因比较复杂,在别的文章里再说吧。

时间: 2024-07-29 03:58:47

UIWebView下各种手势识别器的协作处理方案的相关文章

iOS私有API(三) UIWebView下的手势识别器gestureRecognizer

 首先,UIWebView本身之上并没有手势识别器(gesture recognizer,下面简称手势),而是其子view有. 通过gdb或lldb,我们很容易看到UIWebView的subviews层级关系,下面是使用一个UIWebView打开百度首页时的情况: (lldb) po [g_webView recursiveDescription] $0 = 0x0ab202e0 <UIWebView: 0x7577160; frame = (0 78; 768 926); autoresize

加载带有手势识别器的XIB文件需注意哪些问题_IOS

如果在你的应用程序中需要检测手势,比如点击(tap).二指拨动 (pinch).拖移(pan)和旋转(rotation),那么通过创建UIGestureRecognizer类来实现将十分简单. 接下来小编给大家分享加载带有手势识别器的XIB文件需主要的问题. 首先新建一个继承自UIView的类,并创建相应的XIB文件 #import <UIKit/UIKit.h> @interface ZHDemoView : UIView + (instancetype)demoView; @end 提供一

Android通过滑动实现Activity跳转(手势识别器应用)

通过手势识别器实现界面的转跳,具体内容如下 1.创建 GestureDetector对象 2.创建新类继承SimpleOnGestureListener类(创建 GestureDetecto需要的参数) 3.重写SimpleOnGestureListener中的OnFling()方法.(滑动手势监听) 4.重写界面的OntouchEvent方法 5.通过 GestureDetector对象的onTouchEvent()添加事件 代码如下: public abstract class BaseAc

解决Win8系统下U盘无法打开的方案

  朋友的系统是Windows8,近日在将U盘插入电脑中使用,却遇到无法打开的问题.刚开始以为是U盘坏掉了,后来仔细检查下却发现不是U盘的问题,再检查下驱动程序也没有问题,那到底是哪里出了问题了呢?有什么办法可以迅速解决呢? 解决Win8系统下U盘无法打开的方案: 1.我们这次不双击U盘,而是在u盘上点击右键,仔细看看弹出的右键菜单,如下图.右键菜单中出现两项比较奇怪的菜单,"Open"有朋友就会想:这是怎么添加上的呢?答案只有一个:你的U盘上肯定被偷偷的添加了一些文件进去.我们尝试使

内外网物理隔离下的集群邮件系统路由方案(4)

网卡软开关硬件隔离:网络层隔离:应用层安全验证 5.2 邮件交换效率高 基于Ethernet 的通讯,10M-100M/s 5.3 分布式架构,扩展性强 邮件路由表可以随时修改,可以随时增删隔离区缓冲服务器. 5.4 完全自动运行,无需人工干预,减少人为失误. 系统定时器定时触发邮件路由转发程序,无需人工干预. 5.5 数据同步周期.频率可根据需要和邮件数据量大小随时更改. 提供了更为方便.灵活的选择. 5.6 与邮件系统监控程序配合使用,可以在线监控邮件数据流量,随时掌握系统运行状况. 5.7

Win2000下进程隐藏的一种方案

十分抱歉,匆匆写了几句代码有点bug,即"ZwOpenSection(&g_hMPM,SECTION_MAP_WRITE|SECTION_MAP_WRITE,&attributes)"使得第一次运行返回失败,请删除原文,改正为: pjf (jfpan20000@sina.com) 上次在CVC提到了这东西,因为很简单觉得没必要多说什么,但有人要求写全,所以补充几句: 很多帖子对此论题作了分析,比如APIHOOK.系统服务HOOK等等,至于远线程注入没有自己的进程,本不算

Logtail技术分享(一) : Polling + Inotify 组合下的日志保序采集方案

日志数据采集 提到数据分析,大部分人首先想到的都是Hadoop,流计算,API等数据加工的方式.如果从整个过程来看,数据分析其实包含了4个过程:采集,存储,计算和理解四个步骤. 采集:从各种产生数据的源头,将数据集中到存储系统.包括硬盘上的历史数据,用户网页的点击,传感器等等 存储:以各种适合计算的模式集中式存储数据,其中既包含大规模的存储系统(例如数仓),也有例如临时的存储(例如Kafka类消息中间件) 计算:形态多种多样,但大部分计算完成后会将结果再放入存储 理解:利用机器学习.可视化.通知

Android手势识别器GestureDetector使用详解

以前只知道控件的onTouchEvent()事件,它的动作有MotionEvent.ACTION_DOWN.MotionEvent.ACTION_MOVE.MotionEvent.ACTION_UP;今天有个需求,要监听控件的双击.拖动.滑动等事件,这时onTouchEvent()很明显不能满足我们的需求,经多方打听,找到了今天的主角GestureDetector,下面就对它进行简单的学习. 构造方法: 已过时的有2个,不推荐使用. GestureDetector(GestureDetector

Windows下jsp运行环境的配置方案

js|window 配置前的准备工作: 软件名称 安装包名称 下载地址j2sdk j2sdk-1_4_2-windows-i586.exe http://java.sun.com/Jakarta-Tomcat jakarta-tomcat-5.0.28.zip http://jakarta.apache.org/Apache-Tomcat j2sdk的安装及配置: 1.我的电脑/属性/高级/系统环境变量/path加"E:\j2sdk1.4.2\bin;" ; 2.我的电脑/属性/高级/