在前面的几篇文章中,我们得知了Android中的View之间的层级关系,那么对于触摸事件或者点击事件来说,传递的方向也和层级关系是一致的,从Activity到ViewGroup/View。
对于一次触摸事件或者点击事件,在Android中都是封装了一个MotionEvent来进行处理,对于事件的分发机制也具体的分为三个方法:
1、dispatchTouchEvent(MotionEvent ev) 做分发
2、onInterceptTouchEvent(MotionEvent ev) 做拦截
3、onTouchEvent(MotionEvent ev) 做处理
一: dispatchTouchEvent
先看一下activity的分发事件
其中onUserInteraction()是一个空方法
在之前的文章中得知,getWindow()最终会获取到一个DecorView,DecorView的父类是FrameLayout,FrameLayout的父类是ViewGroup,即ViewGroup的dispatchTouchEvent方法返回true时,activity的dispatchTouchEvent方法也返回true,否则就返回activity的onTouchEvent结果。
那么来看一下ViewGroup的dispatchTouchEvent方法,代码很多,很多也看不懂,没关系,咱们就找感觉大体相关或者根据英文字母的意思能沾边的代码,我们可以看到这么一行代码
final boolean intercepted;
这个是不是就可以认为是做了个boolean类型的参数来判断是否拦截掉了?那么我们把相关的这一块代码单独拎出来
在这个代码块中我们看到当触发了MotionEvent.ACTION_DOWN事件或者它的child不为空时,则进入里面的判断方法,其中intercepted有一种赋值就是ViewGroup的onInterceptTouchEvent方法的返回参数
再返回到dispatchTouchEvent方法中往下看,在if (!canceled && !intercepted) 的判断中,我们看到对子View进行了遍历
而在dispatchTransformedTouchEvent方法中我们看到,调用了子View的dispatchTouchEvent方法去消耗处理此次事件
对于没有子View的情况下则由父View消耗处理事件
再来看View的dispatchTouchEvent方法,可以看到没有了onInterceptTouchEvent方法,而是直接由onTouchEvent来返回处理结果,在View中搜索onInterceptTouchEvent也没有结果,也就是View和ViewGroup不同的地方,View只有dispatchTouchEvent(MotionEvent ev) 和onTouchEvent(MotionEvent ev) 两个方法。
那么至此,事件分发我们也了解的差不多了,当Activity获取到一个点击或者触摸事件后,层层传递到ViewGroup中,当ViewGroup中没有子View或者被ViewGroup自身拦截后,则由父View或者自身处理消耗事件,停止分发。有子View的时候,则向下传递事件。如果有子View进行处理消耗了事件,则停止分发。
网友评论