Android事件分发

  1. 一、基础
    1. 1.事件在哪里传递?
    2. 2.事件
    3. 3.接触的方法
  2. 二、Activity事件分发
  3. 三、ViewGroup事件分发
  4. 四、View

一、基础

1.事件在哪里传递?

Activity
    \
    ViewGroup
            \
            View

2.事件

而在触摸发生的时候就会将事件封装成 MotionEvent 对象。

MotionEvent.ACTION_DOWN:按下View.
MotionEvent.ACTION_UP:抬起View.
MotionEvent.ACTION_MOVEi:滑动View.
MotionEvent.ACTION_CANCEL:结束事件,非人为.

3.接触的方法

dispatchTouchEvent():事件分发.
onInterceptTouchEvent():事件拦截,只存在ViewGroup.
onTouchEvent():事件处理.

一般情况下,给父类调用则会继续分发,返回true则消费,返回false则不处理。

二、Activity事件分发

当点击事件发生的时候,首先事做一个应用的界面上发生的,也就是Activity

public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
// 空方法
onUserInteraction();
}
// 获取PhoneWindow类调用superDispatchTouchEvent()方法
// 其中实现了mDecor.superDispatchTouchEvent(event)
// 在mDecor中则调用其本身的dispatchTouchEvent(event)。这里的DecorView是PhoneWindow内部类,顶层集成ViewGroup
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
// 没有控件接收则调用这里
return onTouchEvent(ev);
}
...
// 没有控件接收则调用这里
public boolean onTouchEvent(MotionEvent event) {
// <font color=#C7254E>处理触摸事件是否在Window边界外</font>
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
return false;
}

Activity<dispatchTouchEvent>
-> 跳转至Window(PhoneWindow)<superDispatchTouchEvent>
-> 跳转至DecorView(ViewGroup)<superDispatchTouchEvent>
-> 跳转至ViewGroup<dispatchTouchEvent>

这里注意分发的时候所调用的类、实现类和方法名称。

三、ViewGroup事件分发

public boolean dispatchTouchEvent(MotionEvent ev) {

// disallowIntercept:是否拦截事件的功能,通过在子控件调用requestDisallowInterceptTouchEvent()方法来阻止拦截
// onInterceptTouchEvent()返回false,则不拦截事件
// onInterceptTouchEvent()返回true,则拦截事件
if (disallowIntercept || !onInterceptTouchEvent(ev)) {

}
}

在这里来分发触摸事件,

true:消费当前事件,并不调用onTouchEvent()方法
false:不消费当前事件,返回至父控件
默认:事件分发

public boolean onInterceptTouchEvent(MotionEvent ev) {  
return false;
}

在ViewGroup中可以通过OnInterceptTouchEvent()来判定是否需要拦截触摸事件,此时会对其子控件通知CANCEL通知

true:拦截当前事件,但是会调用onTouchEvent()方法
false:不拦截,默认

public boolean onTouchEvent(MotionEvent ev) {
return false;
}

此方法会在调用处理点击事件时调用,是在完成自己对点击消费时对应对方法。

true:消费点击事件,不向上传递
false:默认,向上传递

四、View

可以看到View中也有以上几个方法对调用(没有onInterceptTouchEvent方法),过程类似。

在onTouchEvent中:

true:消费当前事件,不调用onClick(),并且不会想上传递
false:不消费当前事件,并且会向父控件传递,并且调用onClick()方法

github