当一个或多个手指触摸屏幕时,通常有四种类型的事件:

  1. ACTION_DOWN:按下屏幕时发生,表示触摸事件开始,他是第一个发生的事件
  2. ACTION_UP:手指抬起,表示触摸事件结束
  3. ACTION_MOVE:手指按下屏幕,并且手指移动的距离超过了某个阈值
  4. ACTION_CANCLE:事件已取消(不是由于用户的行为引起)

这些信息都被包含在MotionEvent中,ACTION_DOWN和ACTION_UP只有一个,而ACTION_MOVE可能存在多个,所谓的事件分发就是队MotionEvent事件分发的过程,就是找到一个能处理MotionEvent的View,过程由Activity开始,传到ViewGroup,最终再传到View,响应过程从上到下,从子到父。

当我们点击一个按钮时,这个按钮可能被包含在ViewGroup中,事件会先从Activity中开始分发进行,如果Activity要自己处理,那么这个按钮就得不到事件信息,如果Activity是进行分发,那么接下来包裹这个按钮的ViewGroup就会得到处理,同样如果这个ViewGroup要进行拦截,那么这个按钮也得不到响应,不拦截的话最终事件会被这个按钮消费。

事件分发由三个方法控制,他们被定义在Activity、View、ViewGroup中:

  • Activity:
public boolean dispatchTouchEvent(MotionEvent ev);
public boolean onTouchEvent(MotionEvent ev);
  • ViewGroup:
public boolean dispatchTouchEvent(MotionEvent ev);
public boolean onInterceptTouchEvent(MotionEvent ev);
public boolean onTouchEvent(MotionEvent ev);
  • View:
public boolean dispatchTouchEvent(MotionEvent ev);
public boolean onTouchEvent(MotionEvent ev);

dispatchTouchEvent

它是事件分发处理函数,如果事件传递到了当前View,那么这个方法会被调用,返回结果表示是否小号当前事件,false表示允许继续分发,返回true表示该事件不再继续分发,有可能是当前View的OnTouchEvent或者是子View的dispatchTouchEvent消费了。

当发生点击操作时,会先从Activity的dispatchTouchEvent方法开始,然后依次传递给子视图,Activity的dispatchTouchEvent方法非常简单,首先判断是不是按下,如果是则调用一下onUserInteraction,然后superDispatchTouchEvent的方法经过层层调用,会传递到View或ViewGroup的dispatchTouchEvent中。

如果superDispatchTouchEvent返回true,则事件结束,表示有View已经消费了,false的话会传递给自身的onTouchEvent方法进行消费,表示所有View的onTouchEvent返回了false,没有人去处理这个时间,只能交给自己去处理。

onInterceptTouchEvent

这个方法是在dispatchTouchEvent中调用的,用来判断是否拦截当前事件,如果当前View拦截了事件,那么在后续同一个事件序列中,这个方法不会被再次调用,默认返回false,返回true表示拦截

如图:

img

onTouchEvent

也在dispatchTouchEvent中调用,用来处理点击事件,如果返回true,则表示当前View消耗了此事件。

注意问题

  1. OnTouchListener的优先级高于onTouchEvent,如果OnTouchListener,onTouchEvent就不执行,反之则会调用

  2. 如果事件一直没有被消费,最后会传给Acitvity,如果Acitivity也不需要就会被抛弃

  3. 判断事件是否被消费是根据返回值,而不是根据你是否使用了事件

  4. onTouchListener,onTouchEvent和onClick的优先级别
    onTouchListener—–>onTouchEvent—>onclick

  5. View的事件分发机制实际上就是一个经典的责任链模式

    责任链模式:当有多个对象均可以处理同一请求的时候,将这些对象串联成一条链,并沿着这条链传递修改请求,知道有对象处理它为止

  6. onClick()方法是在onTouchEvent()方法中的action==ACTION_UP时才执行的,onTouch()、onTouchEvent()、onClick()三个方法的优先级依次递减

  7. Android事件分发机制中,主要是有两个过程,一个是向下分发的过程,该过程主要调用dispatchTouchEvent(),还有一个是向上返回的过程,主要依靠onTouchEvent()方法

  8. view事件执行顺序dispatchTouchEvent-> setOnTouchListener的onTouch->onTouchEvent,如果setOnTouchListener返回ture,后续事件onTouchEvent不再执行

  9. onClick是在onTouchEvent(event)方法中的,所以onTouch优先于onClick执行