前言
这里不讲view基础至少只讲view的事件分发机制
1 概述
1.1 基础概念:
1.1.1什么是点击事件?
我们点击屏幕就会产生一个点击事件即MotionEvent
1.1.2 什么是事件分发?
view事件分发实际上就是点击事件分发也就是MotionEvent分发的过程,MotionEvent产生后我们要通知到具体的view上,这个过程就是事件分发的过程,举个例子,营长(A)想吃xxx于是通知勤务连长(B)连长通知炊事排长©,排长将任务安排给炊事班(D),班长安排给做红烧肉大厨(E),流程如下:
其中营长所说xxx可以理解为是MotionEvent,他包含了具体想吃什么菜(x和y坐标),当事件传递到班长这一级的时候发现MotionEvent内的信息和战士E的做菜范围匹配(x和y坐标),则把MotionEvent传递给战士E来做菜(处理),为什么不是战士G或者H呢?是因为MotionEvent的(x和y坐标)不在他们范围,也就是战士G和战士H不会做红烧肉,而战士E会。
1.1.3 点击事件由外向内和由内向外
如上所描述营长想吃红烧肉就是典型的由外向内,由内向外呢?由上面的例子来描述,战士E不会或者不想做这个菜呢?那他就会通知班长然后班长通知排长以此类推直到营长。
流程简单描述如下:
事件分发由外向内 = Activity->Window->DecroView->viewGroup->具体view
事件分发由内向外 = 具体Wiew->Viewgroup->DecroView->Window-Activity
2 Activity、Window、View的关系解析
Activity包含一个PhoneWidnwo,PhoneWidnwo又将DecorView作为整个窗口的根view
点击事件会首先传给当前的Activity,然后由dispatchTouchEvent方法处理,dispatchTouchEvent内会交给Activity内部的window来
处理
window类是抽象的他的实现类是phoneWindow,然后我们在phoneWindow查找superDispatchTouchEvent方法
superDispatchTouchEvent方法调用了mDecor的superDispatchTouchEvent方法,mDecor是什么?是顶级跟view,mDecor也是个frameLayout,因为继承layout所以mDecor也可以看做是一个viewgroup,而mDecor实际调用了父类的dispatchTouchEvent方法,这也是view事件派发开始的地方,
先上一张图,理解刚刚所说的
dispatchTouchEvent方法我们只关注四个核心部分
如果actionMasked的值是MotionEvent.ACTION_DOWN代表是一个新的事件,会调用条件内方法做重置和清除处理
这里如果MotionEvent.ACTION_DOWN和mFirstTouchTarget != null条件如果成立viewgroup会调用onInterceptTouchEvent判断自身要不要拦截onInterceptTouchEvent默认返回false,但是会收FLAG_DISALLOW_INTERCEPT标记位的影响,一般由子view通过requestDisallowInterceptTouchEvent设置父view要不要拦截ACTION_DOWN以外的事件,mFirstTouchTarget 第一次是空的会走后续流程不会进这个条件,当事件的xy坐标在当前viewgroup的子元素内,mFirstTouchTarget 就会被赋值,然后才会进这个条件。
在这里会从上而下最顶层view向下,判断子view是否在播放动画和点击事件是不是在当前子view的范围内,如果是则跳过本次循环
接着会在dispatchTransformedTouchEvent调用子view的dispatchTouchEvent方法处理,大致流程就是这样