1. 程式人生 > >Android View的事件分發機制筆記

Android View的事件分發機制筆記

  • 涉及到的幾個概念:

    同一個事件序列:手指接觸螢幕的那一刻起,到手指離開螢幕的那一刻結束。這個過程中產生的一系列事件,以down事件開始,中間可能包含多個move事件,最終以up事件結束。正常情況下,一個事件序列只能被一個view攔截且消耗,特殊情況下,這個view也可以將本該自己處理的事件通過onTouchEvent強行傳遞給子view處理。

  • 事件傳遞規則
    public boolean dispatchTouchEvent(MotionEvent ev)用於事件分發。返回結果表示是否消耗當前事件。
    public boolean onInterceptTouchEvent(MotionEvent ev)
    只有ViewGroup有該方法。用來判斷是否攔截某個事件。返回結果表示是否攔截當前事件。預設返回false
    onTouchEvent(MotionEvent event)具體處理事件。返回結果表示是否消耗當前事件。如果不消耗,在同一個事件序列中,當前view無法再次接受到該事件。

上述3個方法關係虛擬碼如下(摘自《Android開發藝術探索》):

public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean consume=false;
        if(onInterceptTouchEvent(ev))
        {
            consume=onTouchEvent(ev);
        }else
{ consume= child.dispatchTouchEvent();//由下級view的dispatchTouchEvent()決定。 } return consume; }

注意:當一個view被設定了OnTouchListener,這時OnTouchListener中的onTouch方法會優先於這個View的onTouchEvent方法。當且僅當OnTouchListener中的onTouch返回false時View自己的onTouchEvent會被執行。
view的dispatchTouchEvent原始碼

ViewGroup的dispatchTouchEvent部分原始碼

因此改進後的事件傳遞虛擬碼如下:

public boolean
dispatchTouchEvent(MotionEvent ev) { boolean consume=disallowIntercept;//由子View設定給父View if(!consume) { consume=onInterceptTouchEvent(ev); } if(consume) { if(mOnTouchListener!=null) { consume=mOnTouchListener.onTouch(this,ev);//優先執行 } if(!consume) { consume=onTouchEvent(ev); } }else{ consume= child.dispatchTouchEvent(); } return consume; }

事件傳遞順序:Activity->Window->View