View的事件分发

4个操作:

  • DOWN: 当用户手指按下时
  • MOVE: 当用户开始滑动时
  • UP: 用户抬起手指
  • CANCEL: 取消操作,事件被无法到达时

3个方法:

  • dispatchTouchEvent()          负责将事件分发到其子View或当前View中
  • onInterceptTouchEvent()     仅存在与ViewGroup中,用于拦截点击事件
  • onTouchEvent()                   完成对点击事件的处理,消耗事件。

事件的传递顺序是 DecorView -> 子View/ViewGroup

事件发生在Activity先调用 getWindow().superDispatchTouchEvent(ev),如果返回true,那么事件被消费。如果返回false表示事件发下去却没有View可以进行处理,则最后return Activity自己的onTouchEvent方法。

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

PhoneWindow,PhoneWindow又回调DecorView的dispatchTouchEvent,所以事件从DecorView向下传。

class PhoneWindow
    // 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);
    }

android view hover事件 android view的事件分发_事件处理

顶层 ViewGroup 的dispatchTouchEvent方法里:

  • 如果这个 ViewGroup 的 onInterceptTouchEvent 返回 true 表示它要拦截这个事件,接着就会调用它的 onTouchEvent 进行处理。
  • 如果不拦截则会交给它的子 view 继续进行分发, 如此反复直到事件被最终处理

onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截.

  1. down事件首先会传递到onInterceptTouchEvent()方法
  2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
  3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。
  4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
  5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

onTouchEvent() 用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。

ViewGroup里的onInterceptTouchEvent默认值是false这样才能把事件传给View里的onTouchEvent.

ViewGroup里的onTouchEvent默认值是false,后续MOVE和UP事件不会传递过来。

View里的onTouchEvent返回默认值是true.这样才能执行多次touch事件。

View中常用的两个方法OnTouch和OnClick

在dispatchTouchEvent中,会首先判断OnTouchListener是否为空,如果设置了onTouchListener,那么OnTouchListener方法中的onTouch方法会被回调。onTouch方法返回true,则onTouchEvent方法不会被调用(onClick事件是在onTouchEvent中调用),否则会直接执行onTouchEvent事件。

dispatchTouchEvent -> onTouch(setOnTouchListener) -> onTouchEvent -> onClick

android view hover事件 android view的事件分发_默认值_02

每个activity都对应一个窗口window,这个窗口是PhoneWindow的实例,PhoneWindow对应的布局是DecorView,是一个FrameLayout,DecorView内部又分为两部分,一部分是ActionBar,另一部分是ContentParent,即activity在setContentView对应的布局。

android view hover事件 android view的事件分发_处理事件_03