Android事件分发理解

Android事件分发机制是个难点和重点,结合下各家,写点本身的理解。。java

首先抛出一个小问题,写一个button的点击事件android

[java]  view plain  copy
 
  1. button.setOnClickListener(new OnClickListener() {    
  2.     @Override    
  3.     public void onClick(View v) {    
  4.         Log.d("TAG", "onClick execute");    

再写一个button的touch事件ide

 

 

[java]  view plain  copy
 
  1. button.setOnTouchListener(new OnTouchListener() {    
  2.     @Override    
  3.     public boolean onTouch(View v, MotionEvent event) {    
  4.         Log.d("TAG", "onTouch execute, action " + event.getAction());    
  5.         return false;    
  6.     }    
  7. });    

结果:this

 

若是把ontouch方法返回值改成true,结果:spa

这是为何?你先能够理解为返回true被消费了,不会往下传递了。.net

你触摸到了任何一个控件,就必定会调用该控件的dispatchTouchEvent方法。那当咱们去点击按钮的时候,就会去调用Button类里的dispatchTouchEvent方法,但是你会发现Button类里并无这个方法,那么就到它的父类TextView里去找一找,你会发现TextView里也没有这个方法,那没办法了,只好继续在TextView的父类View里找一找,这个时候你终于在View里找到了这个方法,示意图以下:3d

而后咱们来看一下View中dispatchTouchEvent方法的源码:orm

[java]  view plain  copy
 
  1. public boolean dispatchTouchEvent(MotionEvent event) {    
  2.     if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&    
  3.             mOnTouchListener.onTouch(this, event)) {    
  4.         return true;    
  5.     }    
  6.     return onTouchEvent(event);    
  7. }    

看这个就明白了:刚才咱们修改的outouch()方法return true,那么就走上面的if语句,被消费了没有执行click方法,若是outouch()ruturn false,那么dispatchTouchEvent()就ruturn onTouchEvent(event),说明了click方法必定在outouchEvent方法里面,点进去看下,果真blog

[java]  view plain  copy
 
  1. public boolean performClick() {    
  2.     sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);    
  3.     if (mOnClickListener != null) {    
  4.         playSoundEffect(SoundEffectConstants.CLICK);    
  5.         mOnClickListener.onClick(this);    
  6.         return true;    
  7.     }    
  8.     return false;    
  9. }    

****************************************************************************************************************************
接下来咱们看一个图递归

 

理解自:

注意:

  • 目前全部的图的事件是针对ACTION_DOWN的,对于ACTION_MOVE和ACTION_UP后面再说。

 

而后总结一下:1.有三层,Activity,ViewGroup,View, 而后呢,分别是dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent,理解为分发,拦截,消费,由于Activity和view在最上和最底层,因此没有onInterceptTouchEvent.

2,接下来认真看下图,有三种返回值,return true,return false, return super,若是只走return super的话那么就是一个U型,整个流程应该是Activity---->ViewGroup--->View 从上往下调用dispatchTouchEvent方法,一直到叶子节点(View)的时候,再由View--->ViewGroup--->Activity从下往上调用onTouchEvent方法。

只要分析dispatchTouchEvent它的四条线路就能够理解这幅图

3.线路1:dispatchTouchEvent和onTouchEvent只要是返回true就是被消费了,没了,不会往下传了

4.线路2:dispatchTouchEvent和onTouchEvent只要是返回false就会回溯给父空间的onTouchEvent处理,相似递归中止开始回溯。

5.dispatchTouchEvent返回super.XXXX()那么就会交给这个ViewGroup的onInterceptTouchEvent 来处理,onInterceptTouchEvent (意思拦截,就是ViewGrouo分发的时候,问一问要不要拦截,若是拦截返回true,若是不拦截返回false,默认return super.onInterceptTouchEvent()就是return false),这里面再分两条路,线路3:到了onInterceptTouchEvent 返回true表示拦截,那么意思说本身要处理,就传给本身的onTouchEvent处理,线路4:onInterceptTouchEvent 默认或者返回false那么就交给子view的dispatchTouchEvent

6.这个时候有人可能会有疑问,子view没有onInterceptTouchEvent ,那么怎么给它的onTouchEvent呢,为了让View能够把事件分发给本身的onTouchEvent,View的dispatchTouchEvent默认实现(super)就是把事件分发给本身的onTouchEvent

 

 

*************************************************************************************************************************8

 

关于ACTION_MOVE 和 ACTION_UP

 
上面讲解的都是针对ACTION_DOWN的事件传递,ACTION_MOVE和ACTION_UP在传递的过程当中并非和ACTION_DOWN 同样,
你在执行ACTION_DOWN的时候返回了false,后面一系列其它的action就不会再获得执行了。简单的说,就是当dispatchTouchEvent在进行事件分发的时候,
只有前一个事件(如ACTION_DOWN)返回true,才会收到ACTION_MOVE和ACTION_UP的事件。

对于ACTION_MOVE、ACTION_UP总结: ACTION_DOWN事件在哪一个控件消费了(return true),
那么ACTION_MOVE和ACTION_UP就会从上往下(经过dispatchTouchEvent)作事件分发往下传,就只会传到这个控件,不会继续往下传,
若是ACTION_DOWN事件是在dispatchTouchEvent消费,那么事件到此为止中止传递,若是ACTION_DOWN事件是在onTouchEvent消费的,
那么会把ACTION_MOVE或ACTION_UP事件传给该控件的onTouchEvent处理并结束传递。
 
 理解自:http://www.jianshu.com/p/e99b5e8bd67b,
http://blog.csdn.net/guolin_blog/article/details/9097463
相关文章
相关标签/搜索