標籤:android 控制項 事件分發
之前遇到事件分發,去網上找相關文章。。。感覺都沒把這幾個的關係說明白。研究了幾篇不錯的文章,今天在這整理一下,希望對大家有所協助。
首先你要知道一點,當你觸摸一個控制項的時候,你就會調用該控制項(或它的父類)的dispatchTouchEvent方法。那我們就來看一下dispatchTouchEvent方法的源碼:
public boolean dispatchTouchEvent(MotionEvent event) { if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && mOnTouchListener.onTouch(this, event)) { return true; } return onTouchEvent(event); }
第一個條件在你setOnTouchListener註冊了監聽器之後就是true了
第二個條件就是它是不是enable的(在xml布局檔案可以設定,button預設為true,imageview為false).關鍵是第三個條件:
button.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return false; // // return true; // } });
也就是說如果我們在onTouch方法裡返回true,就會讓這三個條件全部成立,從而整個方法直接返回true。如果我們在onTouch方法裡返回false,就會再去執行onTouchEvent(event)方法。(onclick是在onTouchEvent中回調的)
所以總結一下:
首先在dispatchTouchEvent中最先執行的就是onTouch方法,如果ontouch返回true,且該控制項是enable的,且已經為其註冊了監聽器, dispatchTouchEvent也就返回true,那麼onTouchEvent就不會執行,onclick也就不會執行了。(返回ture,可以理解為被dispatchTouchEvent它自己消耗了)
如果ontouch返回了false,或者另外兩個條件不成立,onTouchEvent就可以執行了,那麼dispatchTouchEvent的傳回值就得再看onTouchEvent的返回情況了,有點繞(dispatchTouchEvent返回false可以理解為被自己的onTouchEvent消耗了 ,注意在onTouchEvent也是返回true或false,若是true就交給父控制項的ontouchenent並且dispatchTouchEvent也會返回true,如果返回false,dispatchTouchEvent也返回false ,會將事件返回給父 View 的 onTouchEvent 進行消費)
其實還有一種情況,那就是返回 系統預設的 super.dispatchTouchEvent(ev),事件會自動的分發給當前 View 的 onInterceptTouchEvent 方法。
那麼接下了,我們就來看一下onInterceptTouchEvent 了,這個比較好理解。
這裡引用下別人的文章:
onInterceptTouchEvent 的事件攔截邏輯如下:
1 如果 onInterceptTouchEvent 返回 true,則表示將事件進行攔截,並將攔截到的事件交由當前 View 的 onTouchEvent 進行處理;
2 如果 onInterceptTouchEvent 返回 false,則表示將事件允許存取,當前 View 上的事件會被傳遞到子 View 上,再由子 View 的 dispatchTouchEvent 來開始這個事件的分發(重複上一個邏輯);
3 如果 onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev),事件預設會被攔截,並將攔截到的事件交由當前 View 的 onTouchEvent 進行處理。(我覺得此處原文不太對,應該是和返回false作用一樣吧,將事件繼續往下傳到子view上,你怎麼看,歡迎留言。。。0-0)
下面繼續OnTouchEvent:
onTouchEvent用於處理事件,傳回值決定當前控制項是否消費(consume)了這個事件。尤其對於ACTION_DOWN事件,返回true,表示我想要處理後續事件;返回false,表示不關心此事件,並返回由父類的onTouchEvent(區別於onInterceptTouchEvent ,onTouchEvent是向上傳遞,直到遇到true才被消費掉)進行處理。
再總結一下:
onInterceptTouchEvent負責對事件進行攔截,攔截成功後交給最先遇到onTouchEvent返回true的那個view進行處理。onInterceptTouchEvent事件的執行順序是由父控制項到子控制項,並且優先於自己控制項的onTouchEvent方法執行,onTouchEvent事件執行的順序正好相反由子控制項到父控制項
參考文章:
http://blog.csdn.net/fangchao3652/article/details/43191159
http://blog.csdn.net/guolin_blog/article/details/9097463#
http://blog.csdn.net/fangchao3652/article/details/43190601
http://blog.csdn.net/guitk/article/details/7057155
Android dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent詳解