事件分发的大概流程可以这样来描述:Activity ->ViewGroup ->View
事件分发需要的三个重要方法来共同完成
- public boolean dispatchTouchEvent(event):用于进行点击事件的分发
- public boolean onInterceptTouchEvent(event):用于进行点击事件的拦截
- public boolean onTouchEvent(event):用于处理点击事件
三个函数的参数均为even,即上面所说的3种类型的输入事件,返回值均为boolean 类型 上面的三种方法的调用关系大致可以用下面的伪代码来描述:
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean consume = false;//事件是否被消费
if (onInterceptTouchEvent(ev)){//调用onInterceptTouchEvent判断是否拦截事件
consume = onTouchEvent(ev);//如果拦截则调用自身的onTouchEvent方法
}else{
consume = child.dispatchTouchEvent(ev);//不拦截调用子View的dispatchTouchEvent方法
}
return consume;//返回值表示事件是否被消费,true事件终止,false调用父View的onTouchEvent方法
}
onInterceptTouchEvent方法和onTouchEvent方法都在dispatchTouchEvent方法中调用。现在我们根据这段 伪代码来分析一下点击事件分发的传递规则。
首先讲一下点击事件由上而下的传递规则,当点击事件产生后会由 Activity 来处理,传递给 PhoneWindow,再传递给DecorView,最后传递给顶层的ViewGroup。一般在事件传递中只考虑 ViewGroup 的 onInterceptTouchEvent 方法,因为一般情况下我们不会重写 dispatchTouch-Event()方法。对于根 ViewGroup,点击事件首先传递给它的dispatchTouchEvent()方法,如果该ViewGroup的 onInterceptTouchEvent()方法返回true,则表示它要拦截这个事件,这个事件就会交给它的 onTouchEvent()方法处理;如果onInterceptTouchEvent()方法返回false,则表示它不拦截这个事件,则 这个事件会交给它的子元素的dispatchTouchEvent()来处理,如此反复下去。如果传递给底层的View, View是没有子View的,就会调用View的dispatchTouchEvent()方法,一般情况下最终会调用View的 onTouchEvent()方法。
接下来讲解点击事件由下而上的传递。当点击事件传给底层的 View 时,如果其onTouchEvent()方法 返回true,则事件由底层的View消耗并处理;如果返回false则表示该View不做处理,则传递给父View的 onTouchEvent()处理;如果父View的onTouchEvent()仍旧返回false,则继续传递给该父View的父View 处理,如此反复下去。