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
相關文章
相關標籤/搜索