转载于https://www.cnblogs.com/chengxuyinli/p/9979826.html
被分发的对象
被分发的对象是用户触摸屏幕而产生的点击事件,事件主要包括:按下、滑动、抬起与取消。这些事件被封装成MotionEvent对象。
分发事件的组件
也称为分发事件者,包括Activity、View和ViewGroup。它们三者的一般结构为:
分发的核心方法
- dispatchTouchEvent()
- onTouchEvent()
- onInterceptTouchEvent()。
它们并不存在于所有负责分发的组件中
ViewGroup类中,实际是没有onTouchEvent方法的,但是由于ViewGroup继承自View,而View拥有onTouchEvent方法,故ViewGroup的对象也是可以调用onTouchEvent方法的。
事件分发的过程
注意:
- 如果某个组件的该方法返回TRUE,则表示该组件已经对事件进行了处理,不用继续调用其余组件的分发方法,即停止分发。
- 如果某个组件的该方法返回FALSE,则表示该组件不能对该事件进行处理,需要按照规则继续分发事件。在不复写该方法的情况下,都是默认返回False的。
Activity的dispatchTouchEvent方法
// Activity中该方法的核心部分伪代码
public boolean dispatchTouchEvent(MotionEvent ev) {
if (child.dispatchTouchEvent(ev)) {
return true; //如果子View消费了该事件,则返回TRUE,让调用者知道该事件已被消费
} else {
return onTouchEvent(ev); //如果子View没有消费该事件,则调用自身的onTouchEvent尝试处理。
}
}
ViewGroup的dispatchTouchEvent方法
// ViewGroup中该方法的核心部分伪代码
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!onInterceptTouchEvent(ev)) {
return child.dispatchTouchEvent(ev); //不拦截,则传给子View进行分发处理
} else {
return onTouchEvent(ev); //拦截事件,交由自身对象的onTouchEvent方法处理
}
}
View的dispatchTouchEvent方法
// View中该方法的核心部分伪代码
public boolean dispatchTouchEvent(MotionEvent ev) {
//如果该对象的监听成员变量不为空,则会调用其onTouch方法,
if (mOnTouchListener != null && mOnTouchListener.onTouch(this, event)) {
return true; //若onTouch方法返回TRUE,则表示消费了该事件,则dispachtouTouchEvent返回TRUE,让其调用者知道该事件已被消费。
}
return onTouchEvent(ev); //若监听成员为空或onTouch没有消费该事件,则调用对象自身的onTouchEvent方法处理。
}
事件分发是一个递归调用的过程:
事件传到Activity,调用其dispatchTouchEvent方法,方法中再传递给ViewGroup的dispatchTouchEvent处理。
ViewGroup的dispatchTouchEvent方法中,调用onInterceptTouchEvent方法,如果该方法返回True拦截事件,则交给自身的onTouchEvent处理,如果该方法返回false不拦截,则继续传给View的dispatchTouchEvent方法处理。
此时,该递归调用已经到底了,若在View的onTouchListener方法不处理,则调用自身的onTouchEvent处理。
若处理不了,则从递归底部向上返回,依次调用ViewGroup的、Activity的onTouchEvent方法。
注意:onInterceptTouchEvent方法是ViewGroup类对象所独有的,用于对事件进行提前拦截。在一般情况下,该方法是默认返回false的,即不拦截。如果自定义的ViewGroup希望拦截事件,不希望事件继续往子View传播,可以覆写该方法,返回true,即可阻止向下的传播过程。