简介
分析Android中的事件体系其实就是分析MotionEvent对象的处理过程。即当一个事件序列产生之后,系统需要把这一系列的事件交给一个具体的View来进行处理,而传递的过程就是事件的分发。在这个过程中最重要的就是这三个方法:
public boolean dispatchTouchEvent(MotionEvent ev)
用于事件的分发,如果事件能传递给当前的View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和下级dispatchTouchEvent方法的影响,表示是否消耗当前事件。public boolean onInterceptTouchEvent(MotionEvent ev)
用来判断是否拦截某个事件,如果View拦截了某个事件,那么在同一个事件序列中,此方法不会被再次调用。public boolean onTouchEvent(MotionEvent ev)
用于处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次收到事件。
以上的三个方法的关系可以用伪代码形象的表示:
public boolean dispatchTouchEvent(MotionEvent event) {
boolean consume = false;
if(onInterceptTouchEvent(event)){//当前的View拦截该事件
consume = onTouchEvent(event);//当前事件调用onTouchEvent来处理事件
}else{//当前View不拦截该事件,将事件交给下一级的dispatchTouchEvent()
consume = child.dispatchTouchEvent(event);
}
return consume;
}
上边的伪代码形象的表示了事件处理的流程。
事件传递和处理:
产生点击事件之后的传递过程:
Activity->Window->ViewGroup->…..->View
事件的分发:
首先传递给根ViewGroup,他会调用自己的dispatchTouchEvent方法来进行事件的分发:
在根ViewGroup的dispatchTouchEvent方法中首先调用onInterceptTouchEvent方法判断是否拦截该事件:
若onInterceptTouchEvent方法返回true,表示当前的根ViewGroup要拦截该事件,则事件交给该ViewGroup的onTouchEvent方法来处理
若onInterceptTouchEvent方法返回false,表示当前的根ViewGroup不拦截该事件,则事件交给根ViewGroup的下一级ViewGroup
下一级ViewGroup也是同样调用自己的dispatchTouchEvent方法进行事件的分发,直到事件最终被处理。
View处理事件的流程:
当一个View要处理具体事件时,也是按照一定层次顺序进行处理的。
如果该View设置了OnTouchListener,那么OnTouchListener中的onTouch方法会被回调:
若onTouch方法返回true,则该View的onTouchEvent方法就不会被调用
若onTouch方法返回false,则该View的onTouchEvent方法就会被调用
若该View的onTouchEvent方法被调用,若是设置了onClickListener,则调用其中的onClick方法,也就是我们平时常用的onClic方法
所以事件处理时候调用顺序就是:
onTouch->onTouchEvent->onClick
若所有的View的onTouchEvent都返回了false,则事件会一层一层的向上返回,最终会交给Activity来处理,Activity的onTouchEvent方法会被调用。
总结:
一个事件序列是从ACTION_DOWN开始,一直到ACTION_UP为止的中间一系列的操作的序列
正常情况下一个事件序列只能被一个View拦截并消耗,因为当一个事件拦截了ACTION_DOWM事件之后,同一个事件序列就会直接交给他处理,而不会再次调用其onInterceptTouchEvent方法来判断是否拦截。
ViewGrou默认不拦截任何事件,其onInterceptTouchEvent方法默认返回false
View没有onInterceptTouchEvent方法,一旦有事件传递给他,那么就会调用他的onTouchEvent方法
View的onTouchEvent默认是消耗事件的,除非是不可点击状态(clickable和longClickable同时为false)
View的enable属性不影响view的点击事件,即使是不可见的状态,也能响应点击事件。