一、介绍
Android为触摸事件封装了一个类MotionEvent,其实OnTouchEvent的一个参数就是MotionEvent
MotionEvent中封装了触摸点坐标、点击事件类型等
Android中的View可以放在一个ViewGroup中,这个ViewGroup又放在另一ViewGroup中等等,一层层嵌套起来,同一个触摸事件,View和父ViewGroup都想要处理,我们应该传给谁呢,此时就需要事件拦截机制
二、举例说明
完整的事件流程
这就是一个完整的事件流程
事件传递顺序: ViewGroupA -> ViewGroupB -> ViewC
事件处理顺序: ViewC -> ViewGroupB -> ViewGroupA
事件传递返回值: true:拦截,不继续传递 false:不拦截,继续传递
事件处理返回值: true:处理了,不上报 false:处理了,但上报
其实super.onTouchEvent(event)也是false的效果
事件拦截机制:
一系列打断上面完整事件流程的问题都属于事件拦截机制,如下几种情况:
对于ViewGroupA重写一下三个方法
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e(TAG, "ViewGroupA dispatchTouchEvent " + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e(TAG, "ViewGroupA onInterceptTouchEvent " + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(TAG, "ViewGroupA onTouchEvent " + event.getAction() );
return super.onTouchEvent(event);
}
ViewGroupB与ViewGroupA类似
对于ViewC给出一下两个方法
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e(TAG, "ViewC dispatchTouchEvent: " + ev.getAction() );
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(TAG, "ViewC onTouchEvent: " + event.getAction());
return super.onTouchEvent(event);
}
可以看出ViewGroup比View多了一个方法onInterceptTouchEvent,此方法便是事件拦截的核心
之后我们点击C,会与如下日志:
所以可以得出
事件传递顺序:ViewGroupA -> ViewGroupB -> ViewC
事件处理顺序:ViewC -> ViewGroupB -> ViewGroupA
其中
事件传递返回值: true:拦截,不继续传递 false:不拦截,继续传递
事件处理返回值: true:处理了,不上报 false:处理了,但上报
整个事件的流程如下:onInterceptTouchEvent是事件的核心处理方法
举几个图:
1.ViewGroupA把事件传递拦截下来
总经理A发现任务简单,自己处理,没有安排下属,即让ViewGroupA的onInterceptTouchEvent返回true
日志:
流程:
2.ViewGroupB把事件传递拦截下来
部长B把事件拦截下来,自己处理,即让ViewGroupB的onInterceptTouchEvent返回true
日志:
流程
3.ViewC把事件拦截下来
员工最开始要上上级汇报,所以一直返回false,现在让onTouchEvent返回true,自己处理
日志:
流程:
4.ViewGroupB把事件处理结果拦截下来
当员工C把报告上交,部长B发现报告有错误,自己处理,即让ViewGroupB的onTouchEvent返回true
日志:
流程: