今天花了半天时间好好研究了下android中的Touch事件的消费机制,主要是由于前期老师在进行讲解的时候感觉太过于混乱,强记一些根本记不住的结论,也许老师自己水平有限吧,不是在黑。然后自己在网上也百度了一些博客,将的感觉还是过多,一知半解的,不过还是给了我实验的灵感和做出大胆的结论的勇气,首先博主声明,结论有风险,转载还是先注明。
1.首先我们要清楚的是:
Android 中与 Touch 事件相关的方括:dispatchTouchEvent(MotionEventev)、onInterceptTouchEvent(MotionEvent ev)、onTouchEvent(MotionEvent ev);能够响应这些方法的控件包括:ViewGroup、View、Activity。方法与控件的对应关系如下表所示:
Touch 事件相关方法 | 方法功能 | ViewGroup | View | Activity |
public boolean dispatchTouchEvent(MotionEvent ev) | 事件分发 | Yes | Yes | Yes |
public boolean onInterceptTouchEvent(MotionEvent ev) | 事件拦截 | Yes | No | No |
public boolean onTouchEvent(MotionEvent ev) | 事件响应 | Yes | Yes | Yes |
这里的ViewGroup指可以包含子控件的view,也只有其有onIntercepterTouchEvent方法,这里的View指不能包含其他子自控的view。
2.当所有的方法的返回值都为默认值,我们点击View控件的时候,运行的流程为:Activity dispatchTouchEvent-->ViewGroup dispatchTouchEvent-->ViewGroup onInterceptTouchEvent-->View dispatchTouchEvent--> View onTouchEvent--> ViewGroup onTouchEvent--> Activity onTouchEvent,这里只是点击操作的内部流程,接下来的其他操作参考结论。
下面来分析改变返回值该如判断:
1.先从最简单的onInterceptTouchEvent()方法入手,onInterceptTouchEvent针对的是子控件的响应,(当时此时作为父控件的Activity并没有该方法)所以在子控件响应之前,其必会响应;当其返回值为true时,表示拦截起了作用,所以其子控件的所有事件将不会触发,只会进行父和本身自己的事件。返回false和super效果一样。
2.对于onEventTouch方法,当onEventTouch返回值为true时,那么事件就会到此停止,被其消费完毕,比如view的Touch的返回值为true,那么viewGroup和activity的touch事件都不再响应,但是对于其他如移动和抬起事件,该子控件仍然会被触发,所以其父类的intercept事件也会触发,并且和点击的流程一样。返回false和super的效果一样,会将事件向上传递,但是此时好比告诉父控件我不需要touch触发,接下来的操作都不要再来找我了,所以比如接下来的移动和抬起,当前控件不会进行响应,会找寻parent_view进行响应,自然parent的intercept也就不会进行响应了。
3.dispatchEventTouch返回值其实和onEventTouch方法返回值的逻辑其实是一样的,首先,只有在super默认的时候才会向子控件传递,当true的时候,表示不进行向下继续传递,直接在此消费,并且对于接下类的操作,比如移动,抬起仍然会执行;false时,表示直接向父类返回,但是对于接下里的操作,由于第一次的操作返回值是false,系统认为你的dispatch失效,所以剩下的操作直接不让你执行,直接在parent中进行。
4.onEventTouch和dispatchEventTouch再仔细抽取发现设计的 逻辑完全是一样的,返回true时,直接消费该事件,不向任何地方传递,不对接下来事件造成影响;返回false时,直接向父类返回,并且接下来的操作也都直接在父类中响应;默认返回值和false最大区别在于第一个操作动作一个是向下传递,一个是向父类返回。