通过Android的源码去理解整个事件分发的机制。
这个事件分析之后,我会整理成一张简单的流程图供大家理解的。
在分析的时候,首先要知道几个方法和变量的取值
方法
dispatchTouchEvent
onTouch
onInterceptTouchEvent
onTouchEvent
requestDisallowInterceptTouchEvent
onClick
performClick
变量
disallowIntercept
enabled
分析上面方法以及变量的作用
首先事件是从ViewGroup开始传递的,再传递到View
dispatchTouchEvent
当触摸事件发生的时候,整个事件先是从这个方法开始向下传递,他的返回值决定该事件是否被消费。
该方法的开始进入到一个条件判断
disallowIntercept 这个变量和onInterceptTouchEvent这个方法在ViewGroup的dispatchTouchEvent方法中被作为判断条件使用
if(disallowIntercept || !onInterceptTouchEvent()) {
}
disallowIntercept 的返回值是确定的false ---> 引出了另一个方法requestDisallowInterceptTouchEvent 可以通过该方法修改disallowIntercept 的值
onInterceptTouchEvent() 方法 通过观察源码,该方法直接返回一个 false
需要注意的是 这个条件判断中 onInterceptTouchEvent() 方法使用返回值的时候最终的是取反以后使用。
这样这个条件判断成立
此时开始遍历当前布局中的子View
并判断当前的事件是否发生在该View上
如果找到子view 执行这个子View 的 dispatchTouchEvent() 并返回一个true ,表示事件被拦截 所以这个地方会形成一个假象就是 事件是从View开始传递的,这只是一个假象。
子View的dispatchTouchEvent()方法执行
在这个方法的开始也是进入到了一个条件的判断
if(mOnTouchListener!=null && (mViewFlags & ENABLED_MASK) == ENABLED && mTouchListener.onTouch(this, event)) {
return true;
}
如果条件不成立的情况
执行onTouchEvent() 方法
通过这个条件的判断可以看出来
onTouch() 的优先级是高于 onTouchEvent()
在onTouchEvent()中会执行performClick()方法
在performClick()方法中判断当前View有没有注册点击事件,
如果有则执行onClick()事件。
如果没有找到子View 则 继续向下执行,会执行到super.dispatchTouchEvent() 调用父类的 也就是 View的dispatchTouchEvent()方法,ViewGroup的父类是View.
重复上述View的dispatchTouchEvent()
下面是一个简单的流程图