事件拦截分析
说明: LayoutView1、LayoutView2是ViewGroup MyTextView是View “ * ” 标识代表了需要注意的点,完全决定了事件分发
View由外到里层级结构为:LayoutView1-->LayoutView2-->MyTextView
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一、“最外层View事件处理”测试分析
LayoutView1
onInterceptTouchEvent() return false;
onTouchEvent() return true; *
LayoutView2
onInterceptTouchEvent() return false;
onTouchEvent() return false;
MyTextView
onTouchEvent() return false;
拦截条件:最外层LayoutView1 在ACTION_DOWN时return false;并且LayoutView1中onTouchEvent()return true;其余View的onInterceptTouchEvent()和onTouchEvent() 都 return false;
执行动作:滑动屏幕
运行结果:
LayoutView1: onInterceptTouchEvent action:ACTION_DOWN
LayoutView2: onInterceptTouchEvent action:ACTION_DOWN
LayoutView2: onTouchEvent action:ACTION_DOWN
LayoutView1: onTouchEvent action:ACTION_DOWN
LayoutView1: onTouchEvent action:ACTION_MOVE
LayoutView1: onTouchEvent action:ACTION_MOVE
...此处省略LayoutView1onTouchEvent action:ACTION_MOVE多个
LayoutView1: onTouchEvent action:ACTION_MOVE
LayoutView1: onTouchEvent action:ACTION_UP
分析:
因为LayoutView1是ViewGroup并且在onInterceptTouchEvent()的ACTION_DOWN时return false,所以当ACTION_DOWN
动作进入后不进行事件拦截,则事件会传递到LayoutView2的onInterceptTouchEvent(),由于LayoutView2在onInterceptTouchEvent()
方法中ACTION_DOWN时也return false,所以也不拦截事件,则继续下传,但是由于下一个是MyTextView是View没有拦截方法
onInterceptTouchEvent(),则事件拦截结束。则执行LayoutView2的onTouchEvent()方法,由于LayoutView2的onTouchEvent()
在ACTION_DOWN时return false,不进行事件处理,则不会继续执行LayoutView2的Move、up动作,则向父View的onTouchEvent()传递
回传到LayoutView1的onTouchEvent(),因为在ACTION_DOWN时return true,则进行事件处理,继续执行Move、up动作,然后
整个事件执行结束
总结:在事件传递的过程中,如果”所有“的ViewGroup没有拦截事件,则最终会传递到最里层的ViewGroup的OnTouchEvent()如果没有返回true
进行这次的事件处理,则一直会向父View的OnTouchEvent()以此类推传递,知道遇见OnTouchEvent()return true,进行事件
处理后,事件结束,等待下次传递。如果一直没有OnTouchEvent() return true,则传递到最外面,OnTouchEvent()事件结束。
备注:值得注意的是LayoutView1的onInterceptTouchEvent()的ACTION_DOWN时return false后,就不再执行其Move、up了,因为
ACTION_DOWN以后return false”系统“就认为LayoutView1不会拦截事件了,所以ACTION_MOVE、ACTION_UP就没必要传入了
而是把动作直接传递给了OnTouchEvent() return true的View
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二、“第二层View事件处理”测试分析
LayoutView1
onInterceptTouchEvent() return false;
onTouchEvent() return true; *
LayoutView2
onInterceptTouchEvent() return false;
onTouchEvent() return true; *
MyTextView
onTouchEvent() return false;
执行动作:滑动屏幕
运行结果:
LayoutView1: onInterceptTouchEvent action:ACTION_DOWN
LayoutView2: onInterceptTouchEvent action:ACTION_DOWN
LayoutView2: onTouchEvent action:ACTION_DOWN
LayoutView1: onInterceptTouchEvent action:ACTION_MOVE
LayoutView2: onTouchEvent action:ACTION_MOVE
...此处省略N多个:LayoutView1: onInterceptTouchEvent action:ACTION_MOVE LayoutView2: onTouchEvent action:ACTION_MOVE
LayoutView1: onInterceptTouchEvent action:ACTION_MOVE
LayoutView2: onTouchEvent action:ACTION_MOVE
LayoutView1: onInterceptTouchEvent action:ACTION_UP
LayoutView2: onTouchEvent action:ACTION_UP
分析:首先和第一个测试结果进行分析,相同点:测试1的最后一条日志LayoutView1: onTouchEvent action:ACTION_UP,说明事件是在
LayoutView1上结束的,再看看测试结果2最后一条日志LayoutView2: onTouchEvent action:ACTION_UP说明事件是在
LayoutView2上结束的,再由于LayoutView1和LayoutView2的onTouchEvent()都返回了true,很明显可以看出事件传递的
规律了。不同点:<1>那为什么LayoutView1的onTouchEvent() 也return true;却没有执行呢,那是因为,事件传递到了,LayoutView2
的时候在onTouchEvent() return true对事件进行处理了,事件到此就结束了。则不会传递到父类ViewGroup的onTouchEvent()中去了。
<2>看日志 LayoutView1: onInterceptTouchEvent action:ACTION_MOVE、LayoutView2: onTouchEvent action:ACTION_MOVE
LayoutView1: onInterceptTouchEvent action:ACTION_UP、LayoutView2: onTouchEvent action:ACTION_UP,似乎和日志1中
的“总结”有点矛盾了,为什么LayoutView1: onInterceptTouchEvent 在down的时候return false,还是会执行move、up,而看看
LayoutView1: onInterceptTouchEvent 只执行ACTION_DOWN,却没有执行Move、up方法,完全符合测试1的结果,那是因为,在
LayoutView1要把事件传递到子View中,因为子View中进行了事件处理。而LayoutView2却没有执行onInterceptTouchEvent()其Action_move
、Action_up那是因为LayoutView2的子View不是一个ViewGroup,view没有onInterceptTouchEvent()方法。测试结果1和2主要区别就是测试2中
子View进行了事件拦截,而测 试1中父View进行了事件拦截
总结:事件拦截处理需要兼顾整个ViewGroup的所有子ViewGrop,最里层的View总是最先并且左后拦截事件。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
三、”外层View事件拦截“测试分析
LayoutView1
onInterceptTouchEvent() return true; *
onTouchEvent() return true; *
LayoutView2
onInterceptTouchEvent() return false;
onTouchEvent() return false;
MyTextView
onTouchEvent() return false;
执行动作:滑动屏幕
运行结果:
LayoutView1: onInterceptTouchEvent action:ACTION_DOWN
LayoutView1: onTouchEvent action:ACTION_DOWN
LayoutView1: onTouchEvent action:ACTION_MOVE
LayoutView1: onTouchEvent action:ACTION_UP
分析及总结:由于最外层LayoutView1: onInterceptTouchEvent中ACTION_DOWN return true,直接表明对事件进行拦截,则事件不会再传递到LayoutView2
中直接交给 LayoutView1的onTouchEvent()进行处理
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
四、”第二层View事件拦截“测试分析
LayoutView1
onInterceptTouchEvent() return false;
onTouchEvent() return true; *
LayoutView2
onInterceptTouchEvent() return true; *
onTouchEvent() return true; *
MyTextView
onTouchEvent() return false;
执行动作:滑动屏幕
运行结果:
LayoutView1: onInterceptTouchEvent action:ACTION_DOWN
LayoutView2: onInterceptTouchEvent action:ACTION_DOWN
LayoutView2: onTouchEvent action:ACTION_DOWN
LayoutView1: onInterceptTouchEvent action:ACTION_MOVE
LayoutView2: onTouchEvent action:ACTION_MOVE
LayoutView1: onInterceptTouchEvent action:ACTION_UP
LayoutView2: onTouchEvent action:ACTION_UP
分析及总结:根据日志LayoutView2: onInterceptTouchEvent ACTION_DOWN并没有执行move、up方法,因为返回true之后,会直接直接交给其onTouchEvent()
方法,进行事件处理
事件拦截总结:
1、ViewGroup中的onInterceptTouchEvent如果返回true,则直接进行事件拦截,会调用OnTouchEvent()进行拦截后的事件处理。
如果onInterceptTouchEvent返回false,则事件继续向下传递,最终由OnTouchEvent() return true,的viewGroup对事件
进行处理,事件结束。如果没有OnTouchEvent() return true则传到最外层的ViewGroup的OnTouchEvent()事件结束。
2、具体ViewGroup中的onInterceptTouchEvent如果返回false之后,onInterceptTouchEvent()后续的Move、up动作会不会执行
完全取决于当前ViewGrop的子ViewGroup是否进行了拦截处理,如果进行了事件处理,则会执行后续的动作,反之不执行。
本人QQ:2521257722如果有写的不对的地方,请及时联系,或者有什么问题可以一起讨论。共同进步,谢谢!