View的事件分发
2016-07-21 15:18
288 查看
1.事件分发常用的三个函数
public boolean dispathTouchEvent(MotionEvent ev);用来进行事件分发,如果事件能够传递给当前view,那么此方法一定会调用,返回结果受当前View的onTouchEvent和下级View的dispathTouchEvent方法的影响,表示是否消耗当前事件。
public boolean onInterceptTouchEvent(MotionEvent ev);
在上面方法的内部调用,用来表示是够拦截某个事件,如果当前view拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件,viewgroup中才有此事件,view中默认将事件传递给view的onTouchEvent。
public boolean onTouchEvent(MotionEvent ev);
在dispathTouchEvent中调用,用来处理点击事件。返回结果表示是否消耗当前点击事件,如果不消耗,则在同一个事件序列中,当前view无法接收该类事件。
上面所述的三个函数用伪代码表示,理一理他们的执行之间的关系:
public boolean dispathTouchEvent(MotionEvetn ev) { boolean consume=false; if(onInterceptTouchEvent(ev)) { consume=onTouchEvent(ev); }else { consume=child.dispathTouchEvent(ev); } return consume; }
2.点击事件的传递规则
俗话说文不如图,所以我就给大家画了这幅图,还是很直观的。
我们就按照上面的图解释一下事件传递的流程。大致上:Activity->ViewGroup->View这样的事件分发机制,dispatchTouchEvent按照这条线走,View->ViewGroup->Activity这样的事件处理顺序,onTouchEvent按照这条线走。
2.1 Activity的传递过程
传递规则:当一个点击操作发生了,事件最先传递给的肯定是Activity,所以Acticity的dispatchTouchEvent就会开始进行事件分发。具体的工作由Activity内部的Window来完成。Window会将事件传递给Decorview,Decorview一般就是当前界面的底层容器(即setContentView所设置的View的父容器)。通过Activity.getWindow.getDecorView()就可以获得。我们来看一下具体的源码,当然了我们只是看一点点皮毛,毕竟源码这个小妖精还是很折磨人的。Activity.dispatchTouchEvent();
public boolean dispatchTouchEvent(MotionEvent ev) { if(getWindow.superdispatchTouchEvent()) { return true; } return onTouchEvent(ev); }
通过分析上面的代码和图,我们不难发现当Activity分发的事件,下层的viewgroup和view都没有处理时,那么他将亲自出马,这个还是很形象的。在生活中也很常见。比如一个公司的老板有了一个任务,他就交给下面的经理和员工去干,但是很不幸他们都解决不了,那么老板只能说一句:“要你们何用?”,自己去干这个活了。想想真的是代码源自于生活啊。
接下来来看window是如何将事件传递给ViewGroup的。通过源码我们知道,Window是一个抽象类,而window的superdispatchTouchEvent也是一个抽象方法,因此我们必须要找到Window的实现类才行。
由于Window的唯一实现的是PhoneWindow,因此接下来看一下PhotoWindow是如何看处理点击事件。
public boolean superDispatchTouchEvent(MotionEvent ev) { return mDecor.superDispatchTouchEvent(event); }
到这里逻辑就很清晰了,PhoneWindow将事件传递给了Decorview,到了这一层差不多就到了我们的viewgroup了,Decorview的讲解可以看View的基础知识那一节。
2.2 ViewGroup的传递规则
当点击事件到达顶级的view即viewgroup,会调用viewgroup的dispatchTouchEvent的进行事件分发,如果onInterceptTouchEvent返回true,那么事件就不在向viewgroup的下层分发,把点击事件交给viewgroup的onTouchEvent处理。如果onTouchEvent返回true,那么点击事件结束,如果返回false,那么把点击事件交给Activity的onTouchEvent处理。如果onInterceptTouchEvent返回false,那么viewgroup就会将这个事件分发给他的子view。首先遍历
viewgroup的所有子元素,然后判断子元素是够能够接收点击事件:主要通过下面两个条件来衡量:
1.子元素是否在播动画
2.点击事件的坐标是否在子元素的区域内
注意点:执行ViewGroup的onTouchEvent之前,我们还要看一下mOnTouchListener是否被设置,如果没设置,先要执行onTouchListener中的ontouch方法,ontouch的返回值还决定了后面的onTouchEvent能不能执行,假如return true,那么不能执行。
2.3 View的传递规则
view对点击事件的处理过程稍微简单一点,注意这里的view是不包含viewGroup的,假如是viewgroup那么遵循上面的传递规则,因为view是一个单独的元素,它没有子元素因此不需要向下传递事件,所以它只能自己处理事件,首先判断有没有设置onTouchListener,如果OnTouchListener中的onTouch方法返回true,那么onTouchEvent就不会被调用,可见onTouch的优先级是高于onTouchEvent的。相关文章推荐
- Cacti安装脚本Server端+客户端
- iOS开发富文本
- android active间数据传递
- 简单的给mongodb添加用户和认证
- 解决Cannot change version of project facet Dynamic web module to 2.5
- 大学生工资160元,不合情是否合理?
- java基础:Map三两事
- HDU5443->ST表
- leetcode 371
- iOS中上传Array形式的json数据
- PostgreSQL相关配置
- servlet的filter过滤器
- ListView图片加载错乱03
- TCP协议中的三次握手和四次挥手(图解)
- Hbase的Observer
- java中的移位运算符:<<,>>,>>>总结
- IP地址的分类,有效主机范围,私有地址
- 【基于QMediaPlayer的简易视频播放器】— 1、创建基本布局
- PHP isset()与empty()的使用区别详解
- 内核、系统启动崩溃分析