现在的位置: 首页 > 综合 > 正文

View对Touch事件的处理

2019年05月10日 ⁄ 综合 ⁄ 共 2826字 ⁄ 字号 评论关闭

View对Touch的处理过程。首先,Touch事件先到达dispatchTouchEvent(),我们来看看View.dispatchTouchEvent()的源码,这里面涉及到View的onTouchListener,和onTouchEvent()。 

   

Java代码  收藏代码
  1. public boolean dispatchTouchEvent(MotionEvent event) {  
  2.         if (mInputEventConsistencyVerifier != null) {  
  3.             mInputEventConsistencyVerifier.onTouchEvent(event, 0);  
  4.         }  
  5.   
  6.         if (onFilterTouchEventForSecurity(event)) {  
  7.             //noinspection SimplifiableIfStatement  
  8.             ListenerInfo li = mListenerInfo;  
  9.             if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED  
  10.                     && li.mOnTouchListener.onTouch(this, event)) {  
  11.                 return true;  
  12.             }  
  13.   
  14.             if (onTouchEvent(event)) {  
  15.                 return true;  
  16.             }  
  17.         }  
  18.   
  19.         if (mInputEventConsistencyVerifier != null) {  
  20.             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);  
  21.         }  
  22.         return false;  
  23.     }  


        从源码中,我们可以看出View的onTouchListener和onTouchEvent都是在这里被调用的。如果View的touchListener返回true,dispatchTouchEvent()直接就返回,连onTouchEvent都不会被调用了。只有View没有设置onTouchListener,或者touchListener.onTouch()返回false,才会调用onTouchEvent()。 

        我们还可以看出,如果onTouchEvent()被执行了的话,dispatchTouchEvent()的返回值就是onTouchEvent()的返回值。事实上,真正起作用的也就是dispatchTouchEvent(),onTouchEvent()只是被dispatchTouchEvent()调用了而已。

 如果我们把dispatchTouchEvent的返回值改为true,无论onTouchEvent()的返回值是什么,都不影响。 

        现在,我们把dispatchTouchEvent的返回值,改为false看看会怎么样 

Java代码  收藏代码
  1. @Override  
  2.     public boolean dispatchTouchEvent(MotionEvent event) {  
  3.         Utils.log(TAG, "dispatchTouchEvent", event.getAction());  
  4.         super.dispatchTouchEvent(event);  
  5.         return false;  
  6.     }  


        我们在画板上画一条线,看一下日志 


        我们可以看到,只在Touch事件是ACTION_DOWN的时候,打印了一条日志,而且画板上也没有画出一条线。这是说明在ACTION_DOWN的时候,如果dispatchTouchEvent返回false,那么这个View就接收不到后面的触屏事件了。 
        如果我们这样改呢?dispatchTouchEvent()只在ACTION_DOWN的时候,返回true,其他时候返回false。答案是一切又恢复正常了。
 

Java代码  收藏代码
  1. public boolean dispatchTouchEvent(MotionEvent event) {  
  2.         Utils.log(TAG, "dispatchTouchEvent", event.getAction());  
  3.         super.dispatchTouchEvent(event);  
  4.           
  5.         if (event.getAction() == MotionEvent.ACTION_DOWN) {  
  6.             return true;  
  7.         }  
  8.           
  9.         return false;  
  10.     }  


        可以这样理解。每一个触屏事件都必须是以ACTION_DOWN作为开头,后面跟一系列的ACTION_MOVE,最后再有一个ACTION_UP(或ACTION_CANCEL),标识触屏事件结束。所以Android就在ACTION_DOWN的时候做文章,官方文档对dispatchTouchEvent的返回值的解释是:True
if the event was handled by the view, false otherwise。我们可以简单的理解为如果返回true,就说明它需要处理这个事件,就让它接收所有的触屏事件,否则,说明它不用处理,也就不让它接收后续的触屏事件了。

实际上,在将DOWN事件一层层分发到View之前,会先走到其Parent的事件分发,如果View的dispatchTouchEvent返回true,那么,就说明,我们在事件分发的时候,找到了一个合适的Target,当下次再分发MOVE或者UP事件时,发现已经有了这个Target,那么就会直接将事件分发到该Target,即我们处理事件的View。如果dispatchTouchEvent返回false,那就说明我们的这个View对该事件不感兴趣,会交给它的Parent处理,如果parent感兴趣,那下次分发时,就分发到Parent上面去了,反之,如果Parent也不感兴趣,那就是往上层层路由,往上抛出这个事件。

抱歉!评论已关闭.