声明
所谓的点击事件的分发,其实就是MotionEvent事件的分发过程,一般MotionEvent的事件一般是一个事件序列。
事件分发中的三个重要方法
public boolean dispatchTouchEvent(MotionEvent ev);//接收到分发的事件
public boolean onInterceptTouchEvent(MotionEvent ev);//是否拦截接受到的事件
public boolean onTouchEvent(MotionEvent ev);//处理事件
一般来说,三者关系如下代码所示:
public boolean dispatchTouchEvent(MotionEvent ev){//分发到该事件
boolean consume;
if(onInterceptTouchEvent(ev)){//是否拦截该事件
consume = onTouchEvent(ev); //消费掉该事件
}else{
consume = child.dispatchTouchEvent(ev);//将该事件分发给子元素
}
return consume;
}
要注意的点:
当一个View要处理事件的时候,如果他设置了OnTouchListener,那么OnTouchListener中的onTouch方法会被回调。onTouch决定是否处理该事件,如果不处理,再交给View的onTouchEvent方法来处理。也就是OnTouchListener的优先级比onTouchEvent的优先级要高。而我们设置的onClickListener,是在OnTouchEvent里边执行的,也就是OnClickListener的优先级最低。
事件传递机制中的结论
- 同一个事件序列是从手指接触屏幕(down),到离开离开屏幕(up)的过程中产生的所有事件。
- 一般情况下,一个事件只能由一个View来拦截,如果一个元素拦截了某次事件,那么这个事件序列将会直接交给他来处理,切此时他的
onInterceptTouchEvent
也不会在被调用 - 如果一个元素拦截了但是没有消耗
ACTION_DOWN
事件,那么这个事件序列后续的事件不会交给他处理,而转由其父元素处理。 - 但是如果只消耗了
ACTION_DOWN
而不消耗其他事件,那么这个点击事件会消失。 - ViewGroup不拦截任何点击事件
- View没有onInterceptTouchEvent方法,一旦有事件传给他,那么他的onTouchEvent就会被调用
- View的onTouchEvent默认都会消耗事件,除非他是不可点击的。
- View的enable不影响onTouchEvent的默认返回值
- 事件传递的顺序是由内向外的.