android事件攔截和分發機制詳解

上圖,Android整個事件分發機制:


一:事件分發流程

Activity->viewGroup->子view

ViewGroup 及其子類對與 Touch 事件相關的三個方法均能響應,而 Activity 對 onInterceptTouchEvent(MotionEvent ev) 也就是事件攔截不進行響應。另外需要注意的是 View 對 dispatchTouchEvent(MotionEvent ev) 和onInterceptTouchEvent(MotionEvent ev) 的響應的前提是可以向該 View 中添加子 View,如果當前的 View 已經是一個最小的子View(比如 Imageview,Button),那麼就無法向這個最小 View 中添加子 View,也就無法向子 View 進行事件的攔截,所以它沒有onInterceptTouchEvent(MotionEvent ev)。

如圖執行順序是:Activity-1->2->3->4->5->6->7
需要注意的是:activity沒有onInterceptTouchEvent方法,子view中也沒有onInterceptTouchEvent方法。

二:與事件分發的三個重要回調方法

1.   dispatchTouchEvent

return true,事件會分發給當前 View並由 dispatchTouchEvent方法進行消費,同時事件會停止向下傳遞;

 return false,事件分發分爲兩種情況:

如果當前 View 獲取的事件直接來自Activity,則會將事件返回給Activity onTouchEvent 進行消費;如果當前View 獲取的事件來自外層父控件,則會將事件返回給父View   onTouchEvent進行消費。如果返回系統默認的 super.dispatchTouchEvent(ev),事件會自動的分發給當前ViewonInterceptTouchEvent 方法。

2 .  onInterceptTouchEvent

ViewdispatchTouchEvent(MotionEvent ev)方法返回系統默認的 super.dispatchTouchEvent(ev)情況下,事件會自動的分發給當前 ViewonInterceptTouchEvent方法。邏輯返回:

true,則表示將事件進行攔截,並將攔截到的事件交由當前 ViewonTouchEvent進行處理

false,則表示將事件放行,當前 View上的事件會被傳遞到子View上,再由子 ViewdispatchTouchEvent來開始這個事件的分發;返回 super.onInterceptTouchEvent(ev),事件默認會被攔截,並將攔截到的事件交由當前View onTouchEvent 進行處理

3. ontouchEvent:

dispatchTouchEvent返回super.dispatchTouchEvent(ev)並且onInterceptTouchEvent返回true或返回super.onInterceptTouchEvent(ev)的情況下onTouchEvent會被調用。onTouchEvent 的事件響應邏輯如下:

如果事件傳遞到當前 View onTouchEvent 方法,而該方法返回了 false,那麼這個事件會從當View向上傳遞並且都是由上層ViewonTouchEvent來接收,如果傳遞到上面的onTouchEvent 也返回false,這個事件就會消失,而且接收不到下一次事件。

如果返回了 true 則會接收並消費該事件。

如果返回 super.onTouchEvent(ev) 默認處理事件的邏輯和返回 false 時相同。

三:dispatchTouchEvent,ontouchEvent,ontouchListener,onclickListener之間的區別和聯繫

如果一個給一個button同時設置了click和toutch事件,OntouchListener需要一個返回值,如果返回了true,表示把事件消費掉了,onclick事件就不會執行;如果返回false,toutch和click事件能夠同時響應。因爲:在dispatchTouchEvent方法中
public boolean dispatchTouchEvent(MotionEvent event) {  
if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED  
                 && li.mOnTouchListener.onTouch(this, event)) {  
                return true;  
            }
        return false;  
    }
而在ontouchEvent方法裏面調用performclick()方法,onclick在performClick中執行,所以ontouch的優先級比onclick優先級高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章