Android View 事件分發機制

我們在做一些比較絢麗的自定義控件,或者是在做一些絢麗的效果時,都離不開android的事件分發機制。所謂的事件分發機制,其實就是一個MotionEvent事件分發過程,即產生一個MotionEvent事件後,需要將MotionEvent一步一步傳遞到相應的子View,而傳遞的這個過程就是事件分發機制。

我認爲,事件分發機制分爲兩個部分,一部分爲View的事件分發機制,另一部分爲ViewGroup的事件分發機制。我會從源碼角度,帶着問題去分析事件分發機制。

1. 首先先來看看View的事件分發機制

View的事件分發主要有兩個方法
1. dispatchTouchEcent(); 用來分派事件
2. onTouchEvent ();用來處理事件

爲了方便起見,我把View的事件分發源碼整理出來,這裏只展示一部分關鍵代碼,其他的可以自行去看源碼
    public boolean dispatchTouchEvent(MotionEvent event) {
            boolean result = false;
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

            if (!result && onTouchEvent(event)) {
                result = true;
            }
    }

    public boolean onTouchEvent(MotionEvent event) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                     performClickInternal();
                break;
            }
    }
然後就是View事件分發流程圖

View事件分發流程圖

通過源碼我們可以知道
1. 當一個事件進入到當前View,首先會調用dispatchTouchEvent()方法
2. 接下來就會判斷有沒有設置onTouchListener,如果設置並返回true則不執行onTouchEvent,如果沒有設置或者設置了但返回false則執行onTouchEvent。
3. 通過源碼我們可以看到,onClickListener方法其實就是onTouchEvent中up事件中被調用

總結

通過上面源碼分析,我們可以看到,在View中所有事件的執行順序是:
dispatchTouchEvent ->onTouchEventListener -> onTouchEvent -> onClickListener

現象分析
  1. 重寫dispatchTouchEvent、onTouchEvent、設置onTouchEventListener、設置onClickListener的執行效果。
    dispatchTouchEvent.down -> onTouchEventListener.down -> onTouchEvent.down ->
    dispatchTouchEvent.move -> onTouchEventListener.move -> onTouchEvent.move ->
    dispatchTouchEvent.up -> onTouchEventListener.up -> onTouchEvent.up -> onClick
    這個效果符合源碼分析中2中onTouchListener返回false時執行onTouchEvent
  1. 重寫dispatchTouchEvent、onTouchEvent、設置onTouchEventListener、設置onClickListener但是onTouchEventListener返回true的執行效果。
    dispatchTouchEvent.down -> onTouchEventListener.down ->
    dispatchTouchEvent.move -> onTouchEventListener.move ->
    dispatchTouchEvent.up -> onTouchEventListener.up
    這個效果符合源碼分析中2中onTouchListener返回true時不執行onTouchEvent
  1. 重寫dispatchTouchEvent、onTouchEvent、設置onTouchEventListener、設置onClickListener但是dispatchTouchEvent返回值不是super而是true的執行效果
    dispatchTouchEvent.down -> onTouchEventListener.move -> dispatchTouchEvent.up
    這個效果出現的原因,是因爲當我們重寫dispatchTouchEvent沒有返回super,那麼我們就不會調用View的dispatchTouchEvent所以他沒有走onTouchEventListener以下的事件,同理onTouchEvent返回true也是一樣的原因。
思考

不知道大家有沒有發現我有幾個效果在這裏沒有分析

  1. 重寫dispatchTouchEvent、onTouchEvent、設置onTouchEventListener、設置onClickListener但是dispatchTouchEvent返回值不是super而是false的執行效果
  2. 重寫dispatchTouchEvent、onTouchEvent、設置onTouchEventListener、但是不設置onClickListener的執行效果。

至於爲什麼沒有分析,是因爲上面兩個效果,會涉及到ViewGroup的事件分發,想要知道上面兩種會出現什麼效果,以及出現這種效果的原因請移步ViewGroup的事件分發機制,同時View的事件分發機制就到這裏了。

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