事件分发机制:
一个大致的布局:
<ViewGroup1>
<ViewGroup2>
<View/>
</ViewGroup2>
</ViewGroup1>
ViewGroup中有事件分发机制如下:
首先会执行dispatchTouchEvent(MotionEvent ev){}方法。在方法中会调用一下方法:
ViewGroup中比View多了个拦截方法。onInterceptTouchEvent(MotionEvent ev);该方法是默认为false,不拦截传递到子View的触摸事件。intercepted是判断是否拦截事件。
若为true的时候。则在通过一下的方法来判断子View能否获得事件的传递:
处理完是否拦截事件的时候。
// Dispatch to touch targets.
if (mFirstTouchTarget == null) {
// No touch targets so treat this as an ordinary view.
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
final boolean cancelChild = resetCancelNextUpFlag(target.child) || intercepted;
if (dispatchTransformedTouchEvent(ev, cancelChild, target.child, target.pointerIdBits)) {
handled = true;
...
}
}
根据ViewGroup中是否有子View来确定是否有下一级的触摸目标来执行
dispatchTransformedTouchEvent(MotionEvent event, boolean cancel, View child, int desiredPointerIdBits)方法;
那么看看这个方法中都执行了什么东西:
因为ViewGroup继承与View,那么若是没有子View,那么ViewGroup自己执行View的事件分发方法,继而ViewGroup自己消化掉了onTouchEvent()事件。有子View,若是是ViewGroup那么继续执行上面的步骤,若是是View,那么执行View的事件传递执行方法。
总结以上的:
在一开始给的额布局中。我们点击view,日志输出步骤如下:
那么要是需要在父类拦截掉子类的触摸事件,重写onInterceptTouchEvent的方法,让它return true就可以了。
而若是竖直滚动事件和水平滚动事件。则可以通过复写onTouchEvent()事件,在ACTION_MOVE的时候判断手指的方向来判断是否在当前View处理触摸事件还是在上一层View处理滑动事件。
最后,从下面这篇博文中查阅到的资料受到很大的启发:
http://www.codeceo.com/article/view-event-dispatch.html