View的事件分发机制

Android View事件分发机制


当一个点击事件产生后,他的传递过程遵循Activity->Window->View的逐级传递。我们这里讨论的是在Android系统View里事件传递。

1 点击事件的传递规则

点击事件对应Android源码里就是大家常用的MotionEvent。大家知道Android的View是由顶向下的树形结构,有点像HTML的DOM树,点击事件分发就是各层View和ViewGroup对MotionEvent的传递,最终传递到一个具体的View,由他来消费这个MotionEvent.下面介绍事件分发三个重要的方法。

  • boolean dispatchTouchEvent(MotionEvent ev) 用来事件分发,如果事件传递到View这个方法就一定会调用
    返回结果受到当前View和下级View的dispatchTouchEvent影响。
  • boolean onInterceptTouchEvent(MotionEvent ev) 在上面个方法内执行,用来判断是否拦截事件,返回结果表示是否拦截当前事件。
  • boolean onTouchEvent(MotionEvent ev) 在dispatchTouchEvent中调用,用来消费事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View不会再次接受到事件。

用伪代码来表述就是:

public boolean dispatchTouchEvent(MotionEvent ev)
 {
     boolean consume=false;
     if (onInterceptTouchEvent(ev)) {
         consume=onTouchEvent(ev);
     }else{
         consume=child.dispatchTouchEvent(ev);
     }
     return consume;
 }

这里需要注意的是事件只有一个,也只有一次消费或者说处理机会。正常情况下,一个事件序列只能被一个View拦截且消耗掉。当一个View需要处理事件时,如果他设置了OnTouchListner,那么OnTouchListner中的onTouch方法就会被回调。这时事件如何处理还要看onTouch的返回值,如果返回false,者onTouchEvent方法会调用;如果返回true,那么onTouchEvent方法不会被调用。所以OnTouchListner的优先级高于onTouchEvent方法。

无论这个动作是DOWN,MOVE,UP他们的执行顺序是:1、dispatchTouchEvent ; 2、setOnTouchListener的onTouch ; 3、onTouchEvent

这里在说一下View和ViewGroup在事件传递机制的不同的地方,ViewGroup默认不拦截任何事件。Android源码中的ViewGroup的源码的onInterceptTouchEvent方法默认返回false。而View没有onInterceptTouchEvent方法,一旦有点击事件传递给他,他的onTouchEvent就会调用。

View的enable属性不影响onTouchEvent的默认返回值。只要他的cliclable或者longClickable有一个为true,那么他的onTouchEvent就返回true。

特别的一点是事件总是先传递给父元素,然后再有父元素分配给子元素,通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的除ACTION_DOWN外的事件分发过程。

Android View事件机制 21问21答
Android View 事件分发机制源码解析(上)
Android ViewGroup事件分发机制

你可能感兴趣的:(View的事件分发机制)