android view的事件体系(三)

android 事件分发机制的源码分析

1.Activity对点击事件的分发过程

当一个点击操作发生时,事件最先传递给当前的activity,由activity的dispatchTouchEvent来进行派发,

具体工作由activity内部的window完成,window会将事件传递给decorView,通过Activity.getWindow.getDecorView();可以获得

2.源码分析

1.Activity的dispatchTouchEvent:

如果返回true,整个事件循环结束,返回false相当于事件没人处理,所有的View的onTOuchEvent都会返回false,activity的onTouchEvent就会被调用;

2.Activity如何将事件传递给viewGroup的

由于事件是交给activity所附属的window进行分发,window是一个抽象类,window的superDispatchTouchEvent方法也是抽象方法;

由于window唯一实现类是phoneWindow,所以查看phoneWindow源码:

上诉代码:phoneWindow将事件直接传递给decorView;

事件传递到decorView里,由于decorView继承FrameLayout且是父view,所以事件最终会传递给View;

我们要关注的重点是:事件到了view之后如何传递,一般来说顶级视图view都是viewGroup;

 

3.顶级视图view对点击事件的分发过程;

点击事件到达顶级视图view以后,会调用viewGroup的dispatchTouchEvent方法,如果顶级viewGroup拦截事件,onInterceptTouchEvent返回true;事件由ViewGroup处理,如果顶级viewGroup不拦截事件,则事件会传递给他所在的点击事件的子view,这时子view的dispatchTouchEvent会被调用,事件已经从顶级view传递给下一层view,接下来的传递过程和顶级view是一致的,如此循环完成这个事件的分发;

ViewGroup的dispatchTouchEvent方法 分析:

从上诉代码中可以看出:

viewGroup在如下两种情况会判断是否要拦截当前事件;事件类型为ACTION_DOWN或者mFirstTouchTarget!= null. 当事件由viewGroup的子元素成功处理时,mFirstTouchTarget会被赋值并指向子元素; 由于上诉条件为false,将导致viewGroup的onInterceptTouchEvent不会被调用。

如果viewGroup不拦截事件的时候,事件会向下分发到他的子view进行处理:

在上面代码中child传递的不是null,因此他会直接调用子元素的dispatchTouchEvent方法,这样事件就交由子元素处理

如果子元素的第三patchTouchEvent返回true,暂时不用考虑事件在子元素内部怎么发生的,那么mFristTouchTarget就会跳出for循环;

这段代码:这里的第三个参数child为null,前面分析,他会调用super.dispatchTouchEvent(event),

这里就跳到了view的dispatchTouchEvent方法,将事件交给view来进行处理;

4.view对点击事件的处理

先看dispatchTouchEvent方法:

上诉源码中: 首先判断onTouchListener 中的onTOUch方法返回true,那么onTouchEvent就不会被调用,

接下来看onTOuchEvent的实现:

很显然。不可用状态下的view照样会消耗点击事件,

只要view的CLICKABLE 和 LONG_CLICKABLE 有一个为true,那么就会消耗事件,即onTOuchEvent方法返回true; 反之就不会消耗事件,交给他的父级处理;

 

android view的事件体系(二)

https://blog.csdn.net/wk_beicai/article/details/89532160

发布了96 篇原创文章 · 获赞 370 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/wk_beicai/article/details/89599305