Android View事件分发机制(二)

在上一篇呢我们讲了View的事件分发的整体流程,相信大家对View的事件分发机制有了一定的了解,上一篇是针对View的点击事件即Down事件的分发进行分析的,本篇我们主要来分析View在Move和Up的情况下事件是如何进行分发的;
情况1:当父dispatchTouchEvent在进行事件分发的时候,只有前一个事件(如ACTION_DOWN)返回true,才会收到ACTION_MOVE和ACTION_UP的事件。但是如果ACTION_DOWN返回false,这样的结果就是会造成父View的onTouchEvent的调用,同时还有另外一个后果,那就是后续的Move事件、Up事件就都不会再向下传递了,即无法再传递给子View了;
我们来看一下这种情况的log输出,即我们按照默认的模式,即所有Activity、ViewGroup和View,均不处理事件,来看一下整个事件传递的过程包含Move和Up的状态传递;log结果如下:

 Activity___dispatchTouchEvent
 ViewGroup__dispatchTouchEvent
 ViewGroup__onInterceptTouchEvent
 ViewGroup__onTouchEvent___ACTION_DOWN
 Activity___onTouchEvent
 Activity___onTouchEvent___ACTION_DOWN
 Activity___dispatchTouchEvent
 Activity___onTouchEvent___ACTION_MOVE
 Activity___dispatchTouchEvent
 Activity___onTouchEvent___ACTION_MOVE
 Activity___dispatchTouchEvent
 Activity___onTouchEvent___ACTION_MOVE
 Activity___dispatchTouchEvent
 Activity___onTouchEvent___ACTION_UP

可以看到,如果我们在ViewGroup(View)的ACTION_DOWN事件中返回false(super),表示ViewGroup(View)不在接收同一系列(Down、Move、Up)其他的事件,即后续的Move和Up事件均不会再收到;
接下来我画一张图来直观的感受一下
蓝箭头表示Down的事件传递;
橙箭头表示Move和Up的事件传递;

Android View事件分发机制(二)_第1张图片
同一系列事件传递过程

正好印证了我们上面的结论:一旦我们某个View的onTouchEvent方法在Down事件传递时返回false(super=false)它将不会再收到同一系列的其他后续事件了;
情况2:接下来我们来看第二种情况,如果我们在Down事件View的onTouchEvent中消费了该事件(返回true),那么后续的Move和Up事件怎么传递呢,首先我们来看log输出:

 Activity____dispatchTouchEvent
 ViewGroup___dispatchTouchEvent
 ViewGroup___onInterceptTouchEvent
 View________dispatchTouchEvent
 View________onTouchEvent___ACTION_DOWN
 Activity____dispatchTouchEvent
 ViewGroup___dispatchTouchEvent
 ViewGroup___onInterceptTouchEvent
 View________dispatchTouchEvent
 View________onTouchEvent___ACTION_MOVE
 Activity____dispatchTouchEvent
 ViewGroup___dispatchTouchEvent
 ViewGroup___onInterceptTouchEvent
 View________dispatchTouchEvent
 View________onTouchEvent___ACTION_MOVE
 Activity____dispatchTouchEvent
 ViewGroup___dispatchTouchEvent
 ViewGroup___onInterceptTouchEvent
 View________dispatchTouchEvent
 View________onTouchEvent___ACTION_UP

如果觉得看log很乱的话,我们来画一张图直观感受一下:
蓝箭头表示Down的事件传递;
橙箭头表示Move和Up的事件传递;

Android View事件分发机制(二)_第2张图片
图2

可以看到,一旦某个View的onTouchEvent在Down事件中消费事件的话,同一系列后续事件也是只到该View就停止传递;传递规则和Down的一致;
情况3我们再来看一下最后一种情况,如果我们在ViewGroup的onTouchEvent的Down事件中消费事件,后续系列事件是如何传递的;先看Log输出:

 Activity____dispatchTouchEvent
 ViewGroup___dispatchTouchEvent
 ViewGroup___onInterceptTouchEvent
 View________dispatchTouchEvent
 View________onTouchEvent___ACTION_DOWN
 ViewGroup___onTouchEvent___ACTION_DOWN
 Activity____dispatchTouchEvent
 ViewGroup___dispatchTouchEvent
 ViewGroup___onTouchEvent___ACTION_MOVE
 Activity____dispatchTouchEvent
 ViewGroup___dispatchTouchEvent
 ViewGroup___onTouchEvent___ACTION_MOVE
 Activity____dispatchTouchEvent
 ViewGroup___dispatchTouchEvent
 ViewGroup___onTouchEvent___ACTION_UP

图示
蓝箭头表示Down的事件传递;
橙箭头表示Move和Up的事件传递;

Android View事件分发机制(二)_第3张图片
图3

可以看到,View的onTouchEvent在Down事件中返回了false,表示不再接受该系列后续事件,所以后续事件将不会再收到,并且ViewGroup的onInterceptTouchEvent也是只在Down事件时会被调用,同一系列其他事件均不会再被调用;
综上我们得出以下结论:
1、dispatchTouchEvent方法中返回(true和super)Move、Up的事件和Down事件传递规则一致;
2、dispatchTouchEvent方法中返回 false 将不会再收到同一系列Move、Up事件;
3、onInterceptTouchEvent只会收到Down事件;
4、onTouchEvent 方法返回true ,Move、Up的事件和Down事件传递规则一致;
5、onTouchEvent 方法返回false ,将不会再收到同一系列Move、Up事件;

其实总结起来就是一句话,如果你需要Down事件(true),后续的Move和Up事件都会给你,如果你在Down事件时表明态度(false)不处理,你就不会再收到后续的Move和Up事件了;

补充1:在这里我还要多提一句,前面我们说了Down>Move>Up是一系列的事件;那么这里我特别说一下这个Cancel事件,Cancel事件怎么产生呢,如果一个View只收到了Down事件,而没有收到完整一系列的事件(Move、Up)那么就会产生一个Cancel事件;关于其什么时候执行,怎么执行,感兴趣的同学可以自行研究一下;
补充2:另外子控件可以影响父控件是否拦截行为的;通过在子View中dispatchTouchEvent中增加一行代码即可。getParent().requestDisallowInterceptTouchEvent(true);这行代码就可以请求父控件不要拦截事件。很多人可能不太明白这句话的意思,既然事件一定是先到达父控件,然后才到达子View,那也就是getParent().requestDisallowInterceptTouchEvent(true);这句话是在父控件是否拦截判断结束之后才调用,怎么能改变父控件是否拦截的结果呢,这里存在一个执行先后顺序的疑惑。
其实是这样的,getParent().requestDisallowInterceptTouchEvent(true);达到的效果不是修改父控件对本次事件是否拦截的结果,而影响的是后续事件。比如子View在Down事件中调用了getParent().requestDisallowInterceptTouchEvent(true);这行代码,那么在后续Move事件、Up事件产生到达父控件的时候,父控件就不会再拦截了。所以getParent().requestDisallowInterceptTouchEvent(true);只会影响Move事件和Up事件,影响不到Down事件。
至此,Android中View的事件分发机制就介绍完了,相信大家通过上面的介绍会对Android中的View的事件分发机制有更深的理解,理解了View的事件分发机制,可以更好的为我们以后的自定义View和解决View滑动冲突服务,所以掌握View的事件分发至关重要;

你可能感兴趣的:(Android View事件分发机制(二))