本篇博文是Android点击事件分发机制系列博文的第四篇,主要是从解读Activity类的源码入手,根据源码理清Activity点击事件分发原理,并掌握Activity点击事件分法机制。特别声明的是,本源码解读是基于最新的Android6.0版本。
各位童鞋可以参考下面链接进行系统学习
(一)Android6.0触摸事件分发机制解读
(二)Android6.0源码解读之View点击事件分发机制
(三)Android6.0源码解读之ViewGroup点击事件分发机制
(四)Android6.0源码解读之Activity点击事件分发机制
Android中通常点击事件用MotionEvent来表示,当一个点击操作发生时,事件最先传递给当前的Activity,由Activity的dispatchTouchEvent来进行事件的分发,具体工作是由Activity内部的Window来完成的。Window会将事件传递给decor view,decor view一般就是当前界面的底层容器(即setContentView所设置的View的父容器),通过Activity.getWindow.getDecorView()可以获得。关于Activity事件分发机制的源码,我们重点来看下dispatchTouchEvent方法。
(一)dispatchTouchEvent源码解析
/** * Called to process touch screen events. You can override this to * intercept all touch screen events before they are dispatched to the * window. Be sure to call this implementation for touch screen events * that should be handled normally. * * @param ev The touch screen event. * * @return boolean Return true if this event was consumed. */ public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { // 这是个空方法 onUserInteraction(); } //一开始事件交给Activity所附属的Window进行派发,如果返回true,整个事件循环就结束了,返回false意味着事件没人处理,所有人的onTouchEvent都返回了false,那么Activity就要来做最后的收场。 if (getWindow().superDispatchTouchEvent(ev)) { return true; } return onTouchEvent(ev); }123456789101112131415161718192021
onUserInteraction方法
/** * Called as part of the activity lifecycle when an activity is about to go * into the background as the result of user choice. For example, when the * user presses the Home key, {@link #onUserLeaveHint} will be called, but * when an incoming phone call causes the in-call Activity to be automatically * brought to the foreground, {@link #onUserLeaveHint} will not be called on * the activity being interrupted. In cases when it is invoked, this method * is called right before the activity's {@link #onPause} callback. * * <p>This callback and {@link #onUserInteraction} are intended to help * activities manage status bar notifications intelligently; specifically, * for helping activities determine the proper time to cancel a notfication. * * @see #onUserInteraction() */ protected void onUserLeaveHint() { }1234567891011121314151617
(二)onTouchEvent源码解析
通常一个点击操作要是没有被Activity下的任何View处理,则Activity的onTouchEvent将会被调用。返回值为true表明你已经消费了这个事件,false则表示没有消费(默认)。
/** * Called when a touch screen event was not handled by any of the views * under it. This is most useful to process touch events that happen * outside of your window bounds, where there is no view to receive it. * * @param event The touch screen event being processed. * * @return Return true if you have consumed the event, false if you haven't. * The default implementation always returns false. */ public boolean onTouchEvent(MotionEvent event) { // mWindow对象其实就是dispatchTouchEvent方法里的getWindow()对象 if (mWindow.shouldCloseOnTouch(this, event)) { finish(); return true; } return false; }12345678910111213141516171819
事件传递给ViewGroup
接下来我们看Window是如何将事件传递给ViewGroup的。通过源代码我们知道Window是一个抽象类,而Window的superDispatchTouchEvent方法也是个抽象方法,我们来看下。
/** * Used by custom windows, such as Dialog, to pass the touch screen event * further down the view hierarchy. Application developers should * not need to implement or call this. * */ public abstract boolean superDispatchTouchEvent(MotionEvent event);1234567
既然superDispatchTouchEvent是个抽象方法,那么我们去看下它的实现类PhoneWindow是如何处理点击事件的。
@Override public boolean superDispatchTouchEvent(MotionEvent event) { return mDecor.superDispatchTouchEvent(event); }1234
通过以上源码不难发现,PhoneWindow将事件直接传递给了Decor View。我们来看下这里的DecorView。
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker // This is the top-level view of the window, containing the window decor. private DecorView mDecor; @Override public final View getDecorView() { if (mDecor == null) { installDecor(); } return mDecor; }12345678910111213
通常我们通过((ViewGroup)getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0)这种方式获取Activity所设置的View。这个mDecor显然就是getWindow().getDecorView()返回的View,而我们通过setContentView设置的View是它的一个子View。目前事件传递到了DecorView 这里,由于DecorView 继承自FrameLayout且是我们的父View,所以最终事件会传递给我们的View。从这里开始,事件已经传递到我们的顶级View了,所谓的顶级View实际上是最底层View,也叫根View。
参考:《Android开发的艺术》
共同学习,写下你的评论
评论加载中...
作者其他优质文章