1.基础知识
1.事件分发的本质:
当一个点击事件发生后,系统需要将这个事件传递给一个具体的View去处理。这个事件传递的过程就是分发过程。
2>.事件在哪些对象间传递?
一个点击事件产生后,传递顺序是:Activity(Window) -> ViewGroup -> View
3>.事件分发过程由哪些方法协作完成?
dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()
Android事件分发机制的本质是要解决:点击事件由哪个对象发出,经过哪些对象,最终达到哪个对象并最终得到处理。
2.伪代码
// 点击事件产生后,会直接调用dispatchTouchEvent()方法
public boolean dispatchTouchEvent(MotionEvent ev) {
//代表是否消耗事件
boolean consume = false;
if (onInterceptTouchEvent(ev)) {
//如果onInterceptTouchEvent()返回true则代表当前View拦截了点击事件
//则该点击事件则会交给当前View进行处理
//即调用onTouchEvent ()方法去处理点击事件
consume = onTouchEvent (ev) ;
} else {
//如果onInterceptTouchEvent()返回false则代表当前View不拦截点击事件
//则该点击事件则会继续传递给它的子元素
//子元素的dispatchTouchEvent()就会被调用,重复上述过程
//直到点击事件被最终处理为止
consume = child.dispatchTouchEvent (ev) ;
}
return consume;
}
老生常谈了,就不详细研究了~
onTouch()返回true就认为该事件被onTouch()消费掉,因而不会再继续向下传递,即不会执行OnClick()。
3.滑动冲突及处理规则
场景:
①外层左右滑动,内部上下滑动
②内外同上同下
③外层左右,左右,内层上下
处理思路:
①外层滑动,外层View拦截点击事件;内层滑动,内层View拦截点击事件
②根据水平、竖直方向距离差判断
举例子的时候:viewPager已经帮我们解决滑动冲突了,可以说外层是水平scrollView,内层是listview
重点来了!!!!
外层拦截法:所有事件经过父容器的拦截处理,需要拦截则true,不需要则false,onInterceptTouchEvent中,不能在ACTION_DOWN中返回true拦截,因为会导致的所以事件都会交给父容器执行。一般在ACTION_MOVE中拦截,在ACTION_UP中再设置成false恢复。
内层拦截法:父容器不作处理,子容器去判断是否要消耗此事件,重写子容器的dispatchTouchEvent,配合requestDisallowIntercepTouchEvent(boolean),false是叫个父容器处理,true是让父容器不要拦截。