参考链接:http://blog.csdn.net/pi9nc/article/details/9281829#t1
1.了解Android系统的事件拦截机制需要先了解触摸事件,Android触摸事件封装了一个类——MotionEvent.在MotionEvent中我们可以通过event.getY()、event.getX()或者是event.getRawY()、event.getRawX()获取到触摸点的坐标。还可以获取到事件的点击类型,比如MotionEvent.Action_Down、MotionEvent.Action_Move、MotionEvent.Action_Up,在不同的动作中实现不同的逻辑。
2.我们知道 Android 中的View结构是树形结构,view可以放在viewgroup中,但是当view放在一个viewgroup里面,这个viewgroup又可以放在另一个viewgroup中,这样是可以多层嵌套的,当我们队view进行操作的时候,我们到底将触摸事件分配给你哪一个view呢?这就是我们要探讨的问题。
3.代码部分非常简单,创建三个自定义的view。MyViewGroupA/MyViewGroupB/MyView.分别在ViewGroup中重写如下的三个方法.
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d("keke", "MyViewGroupA---- dispatchTouchEvent" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d("keke", "MyViewGroupA---- onInterceptTouchEvent" + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("keke", "MyViewGroupA---- onTouchEvent" + event.getAction());
return super.onTouchEvent(event);
}
MyView中重写两个方法
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("keke", "MyView---- onTouchEvent" + event.getAction());
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d("keke", "MyView----dispatchTouchEvent" + event.getAction());
return super.dispatchTouchEvent(event);
}
4.测试结果如下:
1.不修改任何返回值,代码执行流程如下:
D/keke: MyViewGroupA---- dispatchTouchEvent----0
D/keke: MyViewGroupA---- onInterceptTouchEvent----0
D/keke: MyViewGroupB---- dispatchTouchEvent----0
D/keke: MyViewGroupB---- onInterceptTouchEvent----0
D/keke: MyView----dispatchTouchEvent----0
D/keke: MyView---- onTouchEvent----0
D/keke: MyViewGroupB---- onTouchEvent----0
D/keke: MyViewGroupA---- onTouchEvent----0
所以默认的就是:A(分发)—> A(拦截)—>B(分发)—> B(拦截)—>MyView(分发)—> MyView(处理)—>B(处理)—>A()
2.现在假设在MyViewGroupA分发之后就进行事件的拦截,即事件由MyViewGroupA自己进行处理。那么结果又是这样的:
D/keke: MyViewGroupA---- dispatchTouchEvent----0
D/keke: MyViewGroupA---- onInterceptTouchEvent----0
D/keke: MyViewGroupA---- onTouchEvent----0
当MyViewGroupA中的onInterceptTouchEvent返回true的时候,也就是把事件给拦截了,也就没有MyViewGroupB和MyView的什么事儿了。也就是A(分发)—> A(拦截)—>A(处理)
3现在假设在MyViewGroupB分发之后就进行事件的拦截,即事件由MyViewGroupB自己进行处理。那么结果又是这样的:
D/keke: MyViewGroupA---- dispatchTouchEvent----0
D/keke: MyViewGroupA---- onInterceptTouchEvent----0
D/keke: MyViewGroupB---- dispatchTouchEvent----0
D/keke: MyViewGroupB---- onInterceptTouchEvent----0
D/keke: MyViewGroupB---- onTouchEvent----0
D/keke: MyViewGroupA---- onTouchEvent----0
流程就是:A(分发)—> A(拦截)—>B(分发)—> B(拦截)—>B(处理)—> A(),B处理完成后就通知A即可。
以上是在事件拦截的时候通过返回值的控制。对应的view处理的拦截事件,下面来看看事件的处理,即onTouchEvent事件。
4.当MyView返回值为true或者是false的时候的情况
当为true表示的触摸事件最终由MyView来处理,不要继续向上级进行转发。
D/keke: MyViewGroupA---- dispatchTouchEvent----0
D/keke: MyViewGroupA---- onInterceptTouchEvent----0
D/keke: MyViewGroupB---- dispatchTouchEvent----0
D/keke: MyViewGroupB---- onInterceptTouchEvent----0
D/keke: MyView----dispatchTouchEvent----0
D/keke: MyView---- onTouchEvent----0
当返回false的时候表示的是MyView不处理触摸事件,所以继续向上级进行转发。
D/keke: MyViewGroupA---- dispatchTouchEvent----0
D/keke: MyViewGroupA---- onInterceptTouchEvent----0
D/keke: MyViewGroupB---- dispatchTouchEvent----0
D/keke: MyViewGroupB---- onInterceptTouchEvent----0
D/keke: MyView----dispatchTouchEvent----0
D/keke: MyView---- onTouchEvent----0
D/keke: MyViewGroupB---- onTouchEvent----0
D/keke: MyViewGroupA---- onTouchEvent----0