likes
comments
collection
share

面试串讲008-View的OnTouchEvent,OnClickListener,OnTouchListener三者的执行顺序

作者站长头像
站长
· 阅读数 17

问题:

View的onTouchEvent,OnLongClickListener,OnClickListener,OnTouchListener几者的执行顺序是怎样的?

回答:

这三者的响应顺序依此是diapatchTouchEvent > onTouchListener.onTouch > onTouchEvent > OnLongClickListener > onClickListener,其中任一环节处理事件后,事件则不继续向下分发,View内部的事件处理流程如下图:

面试串讲008-View的OnTouchEvent,OnClickListener,OnTouchListener三者的执行顺序

可以看出不管OnTouchListener.onTouch,onTouchEvent还是OnClickListener.onClick,三者任一返回true,即代表事件被当前View消耗,如果当前View不处理事件,则该事件会向上冒泡,最终被ViewRootImpl处理。

解析:

对于响应事件的View而言,在不考虑父布局拦截事件的前提下,事件流入View的dispatchTouchEvent,在View的onTouchEvent中进行处理。针对一个View而言,我们需要自己处理触摸事件时,通常情况下有三种方式:

  • 设置OnTouchListener
  • 重写onTouchEvent
  • 设置OnClickListener

那么这三者有什么区别呢?触发顺序是怎样的呢?

设置OnTouchListener

为View设置OnTouchListener

 view.setOnTouchListener(new View.OnTouchListener() {
     @Override
     public boolean onTouch(View v, MotionEvent event) {
         return true;
     }
 });

那么我们来看下OnTouchListener.onTouch是在哪里调用的?

 public void setOnTouchListener(OnTouchListener l) {
     getListenerInfo().mOnTouchListener = l;
 }

面试串讲008-View的OnTouchEvent,OnClickListener,OnTouchListener三者的执行顺序

可以看出dispatchTouchEvent会判断是否设置了OnTouchListener,如果设置了的话,就把事件先转交给OnTouchListener处理,OnTouchListener.onTouch返回false再继续分发。

设置OnClickListener

为View设置OnClickListener的代码如下所示:

 view.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
     }
 });

那么我们来看下OnClickListener.onClick是在哪里调用的?

 public void setOnClickListener(@Nullable OnClickListener l) {
     if (!isClickable()) {
         setClickable(true);
     }
     getListenerInfo().mOnClickListener = l;
 }

面试串讲008-View的OnTouchEvent,OnClickListener,OnTouchListener三者的执行顺序

可以看到OnClickListener.onClick是在performClick中调用的,而performClick是在onTouchEvent的ACTION_UP中通过performClickInternal调用的,代码如下:

面试串讲008-View的OnTouchEvent,OnClickListener,OnTouchListener三者的执行顺序

onTouchEvent

从dispatchTouchEvent中可以看到当不设置OnTouchListener或者OnTouchListener.onTouch返回false时,会将事件交给View的onTouchEvent处理,代码如下:

面试串讲008-View的OnTouchEvent,OnClickListener,OnTouchListener三者的执行顺序