本文为事件分发的学习总结。
《Android开发艺术探索》一书中对事件分发做了很详细的介绍。
大神博客:http://blog.csdn.net/singwhatiwanna
//有一个LinearLayout对象:demoLayout
//当demoLayout被点击时,先执行demoLayout的dispatchTouchEvent方法
public boolean dispatchTouchEvent(MotionEvent event){
boolean consume(是否消耗) = false;(不消耗)
boolean intercept(是否拦截此事件) = onInterceptTouchEvent(event)
//(该方法也是demoLayout的方法,并且该方法会返回一个boolean的值来判断是否要拦截此次事件)
if(intercept){
//如果拦截此事件,那么执行demoLayout自己的onTouchEvent方法
consume(是否消耗) = onTouchEvent(event);
//(调用的也是demoLayout的onTouchEvent方法,并且该方法会返回一个boolean的值来判断是否消耗当前事件)
}else{
//如果不拦截此事件,那么事件会传递到demoLayout的子视图的dispatchTouchEvent方法中
consume(是否消耗) = childView.dispatchTouchEvent(event);
//(这时候的dispatchTouchEvent方法就是childView的方法了,不再是demoLayout自己的了)
//而childView调用了dispatchTouchEvent后,又会走一遍childView自己的流程
//当所有都走完(一层一层下去,一层一层返回来后),下面的return consume才会执行
//如果所有的子View都没有消耗该事件,那么会执行demoLayout的onTouchEvent方法
//若onTouchEvent返回false,则后续的事件(比如抬起)都不会被响应
}
return consume;
public class EventRelativeLayout extends RelativeLayout {
private static final String TAG = "EventRelativeLayout";
public EventRelativeLayout(Context context) {
(context);
}
public EventRelativeLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e(TAG, "dispatchTouchEvent:
---父容器的分发事件"+ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e(TAG, "onInterceptTouchEvent:
---父容器的拦截事件"+ev.getAction() );
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(TAG, "onTouchEvent:
---父容器的触摸事件发生"+event.getAction());
return super.onTouchEvent(event);
}
}
public class EventButton extends Button {
private static final String TAG = "EventRelativeLayout";
public EventRelativeLayout(Context context) {
(context);
}
public EventRelativeLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e(TAG, "dispatchTouchEvent: ---"+ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(TAG, "onTouchEvent: ---"+event.getAction());
return super.onTouchEvent(event);
}
}
EventButton: onTouchEvent: —触摸事件发生0
EventRelativeLayout: dispatchTouchEvent: —父容器的分发事件1
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e(TAG, "onInterceptTouchEvent:
---父容器的拦截事件"+ev.getAction());
return true;
}
* 点击Button,事件会传递到子视图Button中,因为Button的clickable的默认值为true,调用Button的onTouchEvent方法。
* 该方法的默认返回值为true(因为Button的clickable默认为true),那么会消耗掉该事件,并且可以接收后续的事件序列,并且父容器的
onTouchEvent方法不会被执行
* 如果将该方法的返回值改为false,表示不会消耗该事件,会将该事件传递给父容器的onTouchEvent,并且不会再接受其后续事件队列。
* 因为其父容器clickable为true,说明可以接收到(抬起)后续的事件队列。
* 但是不会调用父容器的拦截事件方法(因为子View已经拒绝了一次,后续事件都不需要再传递给子View,自然不需要多做一次是否拦截的判断)
* 如果将Button的clickable设置为false,那么调用Button的onTouchEvent方法时该方法会返回false(则不可以接收后续的事件序列)。
* 会一层层回调父容器的onTouchEvent方法
* 点击Button,事件会被父容器EventRelativeLayout拦截,执行父容器的onTouchEvent方法
* 若父容器EventRelativeLayout的clickable属性为false,执行onTouchEvent方法
* 因clickable属性为false,则onTouchEvent也会返回false,无法接收到后续的抬起事件
* 若父容器EventRelativeLayout的clickable属性为true,执行onTouchEvent方法
* 因clickable属性为true,则onTouchEvent也会返回true,可以接收后续的抬起事件
副总监将任务分配给了Android主管,等待主管回复(Window将事件传递给了DecorView)
总监说那拉倒吧
如果技术总监想了想,觉得下面的人应该写不出来(判断是否拦截任务,若拦截),那么后续的任务会再判断是否要拦截,直接执行总监的onTouchEvent