Learn && Live
虚度年华浮萍于世,勤学善思至死不渝
前言
Hey,欢迎阅读Connor学Android系列,这个系列记录了我的Android原理知识学习、复盘过程,欢迎各位大佬阅读斧正!原创不易,转载请注明出处:http://t.csdn.cn/Lmbxd,话不多说我们马上开始!
1.方法介绍
(1)public boolean dispatchTouchEvent(MotionEvent ev):用来进行事件的分发。如果事件能够传递给当前View,那么此方法一定会调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件
(2)public boolean onInterceptTouchEvent(MotionEvent ev):在上一个方法内调用,用来判断是否拦截某个事件,true表示拦截,false表示不会拦截。如果当前View拦截了某个事件,那么在同一个事件序列中,此方法不会被再次调用
(3)public boolean onTouchEvent(MotionEvent event):在dispatchTouchEvent方法中调用,用来处理点击事件,true表示消耗当前事件,false表示不消耗当前事件。如果不消耗,则在同一事件序列中,当前View无法再次接收到事件
下面的伪代码可以表现出三者的关系:
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean consume = false;
if (onInterceptTouchEvent(ev)) {
consume = onTouchEvent(ev);
} else {
consume = child.dispatchTouchEvent(ev);
}
return consume;
}
2.事件传递规则
当一个事件产生后,系统会先根据View树结构由上向下逐级分发事件,再由下向上处理事件,当其中一层拦截并处理事件后,该事件结束
由上向下分发事件顺序:Activity → Window → 顶级View(一般是ViewGroup) → 子层逐级分发事件
由下向上拦截事件顺序:顶级View的其中一个子View的onTouchEvent返回false,则调用上一层的onTouchEvent,逐级向上,若所有元素都不拦截、处理这个事件,最终由Activity的onTouchEvent调用处理
3.几点结论
(1)同一事件序列一定是down —— move —— … —— move —— up
(2)一般情况下,一个事件序列只能被一个View拦截并处理,且同一事件序列中的所有事件都直接交给它处理,且它的onInterceptTouchEvent不会再被调用。但也可以将本该自己处理的事件通过onTouchEvent强行传递给其他View处理
(3)View一旦开始处理事件序列,需要针对不同的事件处理并返回一个boolean值
- 若在处理ACTION_DOWN时返回false,则同一事件序列中的事件不再由它处理,转而调用父元素的onTouchEvent处理。
- 若在处理除ACTION_DOWN以外的其他事件时返回false,则不会交由父元素处理,且当前View可以接收后续的事件,最终这些未被处理的事件会传递给Activity处理
(4)ViewGroup默认不拦截任何事件,即ViewGroup的onInterceptTouchEvent默认返回false
(5)View没有onInterceptTouchEvent,一旦有事件传递给它,直接调用onTouchEvent
(6)View的enable属性不影响onTouchEvent的默认返回值。只要它的clickable或longClickable有一个为true,onTouchEvent就返回true
(7)onClick被调用的前提是View是clickable的,且收到了down、up事件
ent
(8)事件的传递总是先父后子,但requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,但ACTION_DOWN事件除外