View 事件分发主要关注三个方法:
public boolean dispatchTouchEvent(MotionEvent ev)
public boolean onInterceptTouchEvent(MotionEvent ev)
public boolean onTouchEvent(MotionEvent event)
注意:onInterceptTouchEvent 方法只有 ViewGroup 中才有, View 中是没有的。
我们先通过一个简单的 Demo 来看看这几个方法的执行顺序。
一个自定义 RelativeLayout 嵌套一个自定义 TestView,重写上述三个方法,打印日志:
通过日志打印的顺序,我们可以试着分析下流程,首先调用了 parent 的 dispatchTouchEvent, 在其中调用了 onInterceptTouchEvent ,当 onInterceptTouchEvent 返回 false 时,分发给 child 并调用 child 的 dispatchTouchEvent, 在 child 的 dispatchTouchEvent 中调用了 onTouchEvent 由于也返回 false 最终调用 parent 的 onTouchEvent.
貌似有点绕,这个分析流程到底对不对,还得看源码。。
我们在 ViewGroup 的 dispatchTouchEvent 中找到了 onInterceptTouchEvent()方法的调用。
这里是 onInterceptTouchEvent()做的事情。
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.isFromSource(InputDevice.SOURCE_MOUSE)
&& ev.getAction() == MotionEvent.ACTION_DOWN
&& ev.isButtonPressed(MotionEvent.BUTTON_PRIMARY)
&& isOnScrollbarThumb(ev.getX(), ev.getY())) {
return true;
}
return false;
}
下面是调用 child 的 dispatchTouchEvent 方法的地方:
if (!canceled && !intercepted) {
....
for (int i = childrenCount - 1; i >= 0; i--) {
...
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
...
}
}
}
在 dispatchTransformedTouchEvent() 方法中:
handled = child.dispatchTouchEvent(event);
整个流程就基本上清楚了:总结一下看看:
public boolean dispatchTouchEvent(MotionEvent ev){
boolean handled= false;
if(onInterceptTouchEvent(ev)){
hanlde = onTouchEvent(ev);
}else{
handle = child.dispathTouchEvent(ev);
}
return handled;
}
下面回到最开始,当我们在 parent 的 dispatchTouchEvent 方法返回 true 时的情况会是怎样?
仅仅只有 parent 的 dispatchTouchEvent ;
next: 在 parent 的 onInterceptTouchEvent 返回 true 时的情况:
parent 的三个方法都有调用到!!!
我们再看看 在 parent 的 onTouchEvent 中去返回 true 的情况。