一文读懂 Android TouchEvent 事件分发、拦截、处理过程 (2)

把ViewGroup2.java的dispatchTouchEvent修改一下,return 返回true使事件不在分发

@Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i(TAG, "dispatchTouchEvent action:" + StringUtils.getMotionEventName(ev)); Log.d(TAG, "onInterceptTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + true); return true; }

此时的Log

一文读懂 Android TouchEvent 事件分发、拦截、处理过程

一文读懂 Android TouchEvent 事件分发、拦截、处理过程

从图片可以看出,当ViewGroupon2的dispatchTouchEvent返回true后,事件不会再分发传送到ViewGroup3了,也不会分发到Activity的onTouchEvent了。而是事件到了ViewGroupon2的dispatchTouchEvent后,就停止了。dispatchTouchEvent返回true表示着事件不用再分发下去了。

四、ViewGroup2的onInterceptTouchEvent返回true

把ViewGroup2.java的onInterceptTouchEvent修改一下,return 返回true把事件拦截了

@Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i(TAG, "dispatchTouchEvent action:" + StringUtils.getMotionEventName(ev)); boolean superReturn = super.dispatchTouchEvent(ev); Log.d(TAG, "dispatchTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + superReturn); return superReturn; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i(TAG, "onInterceptTouchEvent action:" + StringUtils.getMotionEventName(ev)); Log.d(TAG, "onInterceptTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + true); return true; }

此时的Log

一文读懂 Android TouchEvent 事件分发、拦截、处理过程


一文读懂 Android TouchEvent 事件分发、拦截、处理过程

可以看出ViewGroup2拦截了事件,就不会继续分发到ViewGroup3;而且ViewGroup3拦截了事件又不处理事件,会把事件传递到Activity的onTouchEvent方法。

五、ViewGroup2的onInterceptTouchEvent、onTouchEvent返回true

把ViewGroup2.java的onTouchEvent修改一下,return 返回true把事件处理了

@Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i(TAG, "onInterceptTouchEvent action:" + StringUtils.getMotionEventName(ev)); Log.d(TAG, "onInterceptTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + true); return true; } @Override public boolean onTouchEvent(MotionEvent ev) { Log.i(TAG, "onTouchEvent action:" + StringUtils.getMotionEventName(ev)); Log.d(TAG, "onTouchEvent action:" + StringUtils.getMotionEventName(ev) + " " + true); return true; }

一文读懂 Android TouchEvent 事件分发、拦截、处理过程


一文读懂 Android TouchEvent 事件分发、拦截、处理过程

从流程可以总结出,当ViewGroup2的onInterceptTouchEvent、onTouchEvent都返回true时,事件最终会走到ViewGroup2的onTouchEvent方法处理事件,后续的事件都会走到这里来。

上面通过log分析很清楚了,是不是就这样够了?其实还不行,还要从源码的角度去分析下,为什么事件会这样分发。

二、通过源码分析事件分发 一、Activity的dispatchTouchEvent

先看看Activity下的dispatchTouchEvent

public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); } if (getWindow().superDispatchTouchEvent(ev)) { return true; } return onTouchEvent(ev); }

onUserInteraction方法

public void onUserInteraction() { }

从代码可以了解

调用Activity的onUserInteraction方法,action为down时会进去onUserInteraction方法,但是这个是空方法不做任何事情,可以忽略。

调用window的superDispatchTouchEvent方法,返回true时事件分发处理结束,否则会调用Activity的onTouchEvent方法。

调用Activity的onTouchEvent方法,进入这个条件的方法是window的superDispatchTouchEvent方法返回false。从上面的分析(二、不拦截处理任何事件)可以知道,所有子View的dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent都返回false时会调动Activity的onTouchEvent方法,这个时候也是使window的superDispatchTouchEvent方法返回false成立。

二、window的superDispatchTouchEvent

Activity的getWindow方法

public Window getWindow() { return mWindow; }

mWindow是如何赋值的?
是在Activity的attach方法赋值的,其实mWindow是PhoneWindow。

Activity的attach方法

final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) { attachBaseContext(context); mFragments.attachHost(null /*parent*/); mWindow = new PhoneWindow(this, window, activityConfigCallback); mWindow.setWindowControllerCallback(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); ... }

PhoneWindow的superDispatchTouchEvent方法

private DecorView mDecor; @Override public boolean superDispatchTouchEvent(MotionEvent event) { return mDecor.superDispatchTouchEvent(event); }

DevorView的superDispatchTouchEvent

public boolean superDispatchTouchEvent(MotionEvent event) { return super.dispatchTouchEvent(event); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzgsxp.html