事件分发是作为一名Android开发者必须要掌握的东西,下面我们来一起探究下是如何进行事件分发的
首先我们要搞明白,什么是事件分发?Android中的视图是由一个个View嵌套构成的层级视图,即一个View里包含有子View,而这个子View里面又可以再添加View。当用户触摸屏幕产生一系列事件时,事件会由高到低,由外向内依次传递,最终把事件交到一个具体的View手上处理,这个传递的过程就叫做事件分发。
事件分发的顺序 Activity->ViewGroup->View
支持事件分发的方法dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent
下面我们先来探究下事件分发的顺序
当手机屏幕发生了点击事件时,首先调用的是Activity的dispatchTouchEvent方法,起主要代码如下:
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
调用了getWindow().superDispatchTouchEvent(ev)方法,
public
return mWindow;
}
getWindow方法返回了一个Window对象,这个Window对象是一个抽象类,他的唯一实现是PhoneWindow,你说我是怎么知道的?上注释
好的我们在去PhoneWindow中看下superDispatchTouchEvent方法,源码是在frameworks层。路径
.frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
到这里发现了DecorView,干啥的呢?注释说明的很清楚,他是window的顶层视图
我们在去DecorView中看下superDispatchTouchEvent方法
public boolean superDispatchTouchEvent (MotionEvent event) {
return super .dispatchTouchEvent(event); }
调用了父类的dispatchTouchEvent, DecorView extends FrameLayout,有的人说我怎么在FrameLayout中找不到这个方法呢,是的我也找不到为啥呢?FrameLayout extends ViewGroup,明白了吧,我们直接去ViewGroup中看看有没有
代码太多就不放了,路径在android.view下
在ViewGroup中的 dispatchTouchEvent方法默认访问了onInterceptTouchEvent
// Check for interception.
final boolean
intercepted = onInterceptTouchEvent(ev);
然后调用了dispatchTransformedTouchEvent并传递了四个参数,注意第三个参数是null
// No touch targets so treat this as an ordinary view.
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
在 dispatchTransformedTouchEvent方法中,第三个参数是child,看看child==null时做了什么操作
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean
View child, int
if (child == null) {
handled = super.dispatchTouchEvent(event);
} else
handled = child.dispatchTouchEvent(event);
}
child是null时,调用了父类的dispatchTouchEvent方法,我们在接着往下看ViewGroup extends View,
直接看View中的dispatchTouchEvent方法,在View中的dispatchTouchEvent方法中调用了自身的onTouchEvent方法,并默认返回一个false。
到这里整个事件的分发顺序我们是不是就清楚了,Activity->ViewGroup->View,老铁们,很清楚有木有!有的同学要说了View默认返回false或者有返回true的情况在然后呢,下面这些就不一一分析了,一大段的代码文字看着也烦,大家根据我这个思路自己过一遍framework源码即可,下面在给大家整体上一张事件分发流程图
简单的总结下:
Activity收到触屏分发事件后对自己的dispatchTouchEvent说,你给我把这个事件处理下,Activity的dispatchTouchEvent收到指令不想干,他对他的小弟ViewGroup中的dispatchTouchEvent说你把这个事件处理下,ViewGroup中的dispatchTouchEvent也不想干活啊,他对自己家的onInterceptTouchEvent说,这个事件交给你,赶紧处理下,onInterceptTouchEvent也是有脾气的,你们都不干让我干,我也不干,他手下也有小弟,于是对他手下的小弟View中的dispatchTouchEvent说,这个问题你看看,是不是你们团队的搞的bug,赶紧处理下,View团队的dispatchTouchEvent于是将问题提交给了他们团队专门处理问题的onTouchEvent,onTouchEvent经过三天三夜的苦战研究发现解决不了,于是上报给了ViewGroup团队的onTouchEvent,ViewGroup团队的onTouchEvent接到小弟的上报问题后,发现自己也处理不了,于是又上报给了Activity团队的onTouchEvent,Activity团队的onTouchEvent接到小弟的上报问题后发现时间过去太久了,客户都不用这个系统了,直接扔一边去了爱咋地咋地吧。