在Android的触摸点击等事件中我们经常需要用到时间分发机制,看了很多朋友写的博客,感觉不是很明朗,综合多家的精粹用通俗的描述全面的介绍下事件分发机制。
1。首先来一张全局图
1代表我们的activity
2代表我们的viewgroup 也就是我们经常说的容器
3 就是最顶层的view了 比偶如说 textview imageview等
先简单的介绍下,稍后再代码分析
当点击最顶层的view的时候
down事件经过: activity的分发机制函数 dispatchTouchEvent 当返回true或者false的时候事件就在分发中就会被消费,不会传到上一层,也不会执行activity的 onTouchEvent
/**
* 事件的分发
* 分发事件的方法。当接收到事件时,通过调用此方法来决定是否分发。
* @param ev
* @return
* true: 事件不再进行分发且已经在自身事件的分发中被消费
* false: 也不对事件进行分发。
* 也就是说该方法不论是返回true还是返回false都不会对事件进行分发,
*
* 只有当返回系统默认super.dispatchTouchEvent(ev)时,才会将事件分发给本层
* 的拦截事件onInterceptTouchEvent(MotionEvent ev)去处理,如果没有onInterceptTouchEvent(MotionEvent ev)方法
* 则直接分发给子View中的onInterceptTouchEvent(MotionEvent ev)方法处理
*
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_DOWN){
Log.d("data","[LinearLayout]--dispatchTouchEvent:"+ev.getAction()+" "+super.dispatchTouchEvent(ev));
}
return super.dispatchTouchEvent(ev);
}
/*log日志
*EventActivity: dispatchTouchEvent=====ACTION_DOWN
*EventActivity: dispatchTouchEvent=====ACTION_UP
*/
activity的 dispatchTouchEvent返回super.dispatchTouchEvent(ev)的时候事件往下传递进入viewgroup的分发机制中,
如果viewgroup的 dispatchTouchEvent返回true/false的时候,事件不会被往下分发,而是回传到activity的onTouchEvent去消费事件,在activity中的onTouchEvent执行完事件后如果返回true表示消费了这个事件,传递到此结束,返回false表示不处理事件,继续分发,此时事件就丢失了
如果viewgroup的 dispatchTouchEvent返回super.dispatchTouchEvent(ev);的时候,down事件就会继续继续向上传递,到达View顶层的dispatchTouchEvent,如果View的dispatchTouchEvent返回true/false的时候,事件会传递给viewgroup的onTouchEvent去消费事件,只有返回super.dispatchTouchEvent(ev);才会调用本层的onTouchEvent,如果本层onTouchEvent返回true,事件到此结束,相当于消耗了事件。如果返回false的话,接下来的move和up事件将不会分配给View,而是直接在viewgroup的onTouchEvent去消费事件。
ViewGroup特有的时间拦截 onInterceptTouchEvent
/**
* 事件的拦截
* 拦截事件方法,该方法只有在布局或者ViewGroup中才会有。通过调用该方法来决定是否对事件
* 进行拦截。
* @param ev
* @return
* true:进行拦截,将事件进行分发onTouchEvent方法处理
* false:不对事件进行拦截,传递给下一级处理
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(ev.getAction() ==MotionEvent.ACTION_DOWN){
Log.d("data","[LinearLayout]--onInterceptTouchEvent:"+ev.getAction()+" "+super.onInterceptTouchEvent(ev));
}
return super.onInterceptTouchEvent(ev);
}
事件处理函数
/**
* 事件的处理
* 处理事件。当对事件进行了拦截时,将会调用onTouchEvent方法对事件进行处理。
*
* @param ev
* @return
* true:表示该View能处理该事件,事件将终止向上传递(传递给其父View)
* false:不能处理,则把事件传递给其父View的onTouchEvent方法来处理
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
if(ev.getAction() ==MotionEvent.ACTION_DOWN){
Log.d("data","[LinearLayout]--onTouchEvent:"+ev.getAction()+" "+super.onTouchEvent(ev));
}
return super.onTouchEvent(ev);
}
//注意:onTouchEvent事件消费函数一旦返回false 后面的鼠标UP 和 MOVE 就不会在这里执行了,但是下一次down事件能获取到
Android中的事件在表现形式上有很多,如onTouch、onClick和onLongClick等,在具体微观上的表现形式有action_down、action_move和action_up等。但是不管是哪种表现形式,都是基于事件的传递。