android点击事件源码,Android6.0 源码解读之 Activity 点击事件分发机制

本篇博文是Android点击事件分发机制系列博文的第四篇,主要是从解读Activity类的源码入手,根据源码理清Activity点击事件分发原理,并掌握Activity点击事件分法机制。特别声明的是,本源码解读是基于最新的Android6.0版本。

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();

}

if (getWindow().superDispatchTouchEvent(ev)) {

return true;

}

return onTouchEvent(ev);

}复制代码

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

* when an incoming phone call causes the in-call Activity to be automatically

* brought to the foreground, {@link

* the activity being interrupted. In cases when it is invoked, this method

* is called right before the activity's {@link

*

* 复制代码

This callback and {@link

* activities manage status bar notifications intelligently; specifically,

* for helping activities determine the proper time to cancel a notfication.

*

* @see

*/

protected void onUserLeaveHint() {

}

(二)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) {

if (mWindow.shouldCloseOnTouch(this, event)) {

finish();

return true;

}

return false;

}复制代码

事件传递给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);复制代码

既然superDispatchTouchEvent是个抽象方法,那么我们去看下它的实现类PhoneWindow是如何处理点击事件的。

@Override

public boolean superDispatchTouchEvent(MotionEvent event) {

return mDecor.superDispatchTouchEvent(event);

}复制代码

通过以上源码不难发现,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;

}

复制代码

通常我们通过((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开发的艺术》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值