1. 程式人生 > >Android面試準備:事件分發機制

Android面試準備:事件分發機制

View的事件分發機制舉例

  1. 為按鈕設定onClick點選事件和onTouch觸控事件的執行順序為:
    1、onClick事件:
button.setOnClickListener(new OnClickListener() {  
    @Override  
    public void onClick(View v) {  
        Log.d("TAG", "onClick execute");  
    }  
});  

2、onTouch事件:

button.setOnTouchListener(new OnTouchListener() {  
    @Override  
    public
boolean onTouch(View v, MotionEvent event) { Log.d("TAG", "onTouch execute, action " + event.getAction()); return false; } });

3、執行次序為:
onTouch是優先於onClick執行的,並且onTouch執行了兩次,一次是按下ACTION_DOWN,一次是擡起ACTION_UP(你還可能會有多次移動ACTION_MOVE的執行,如果你手抖了一下)。因此事件傳遞的順序是先經過onTouch,再傳遞到onClick。
4、onTouch方法是有返回值的,這裡我們返回的是false,表示事件會繼續傳遞;為true表示事件不繼續傳遞了。(可以理解成事件被onTouch消費掉了)

  1. 只要你觸控到了任何一個控制元件,就一定會呼叫該控制元件的dispatchTouchEvent方法(該方法在View中)
    dispatchTouchEvent原始碼為:
public boolean dispatchTouchEvent(MotionEvent event) {  
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
            mOnTouchListener.onTouch(this, event)) {  
        return
true; } return onTouchEvent(event); }

1、如果條件為真,則執行onTouch(this, event)方法,否則執行的是onTouchEvent(event);
3、三個條件依次是:註冊監聽 + 控制元件處於enabled狀態 + onTouch方法的返回值(也就是如果這個onTouch回撥函式的返回值為true,則執行onTouch而不會執行 onTouchEvent(event),否則執行的是onTouchEvent(event),這就是為什麼剛剛說“被消耗掉”了的原因)
3、onClick方法在onTouchEvent(event)方法中,當按鈕狀態為MotionEvent.ACTION_UP(即點選)時,會執行performClick()方法裡回撥被點選控制元件的onClick方方法

  1. 就是touch事件的層級傳遞。
    1、我們都知道如果給一個控制元件註冊了touch事件,每次點選它的時候都會觸發一系列的ACTION_DOWN,ACTION_MOVE,ACTION_UP等事件。這裡需要注意,如果你在執行ACTION_DOWN的時候返回了false,後面一系列其它的action就不會再得到執行了。簡單的說,就是當dispatchTouchEvent在進行事件分發的時候,只有前一個action返回true,才會觸發後一個action。
    2、touch事件分發的機制總結為:
    就拿按鈕點選事件為例的touch事件分發的執行過程為:
    ①、當觸控到了任何一個控制元件,就一定會呼叫該控制元件的dispatchTouchEvent方法
    ②、dispatchTouchEvent方法中首先會執行onTouch這個回撥函式,但是執行onTouch這個回撥函式有兩個前提條件、第一個提前提條件是該控制元件註冊了觸控監聽,第二個條件是該控制元件是的狀態是Enable的。
    ③、onTouch回撥函式會有一個返回值,返回這如果為true的話就代表本次觸控事件被消耗掉了,執行接觸;返回值為false的話會繼續執行onTouchEvent方法。
    ④、onTouchEvent方法就是真正執行點選事件的地方,也就是我們重寫的onClick方法。
    ⑤、onTouchEvent方法中能夠捕獲一次點選事件當中ACTION_DOWN、ACTION_ MOVE、ACTION_UP這三個中作,當觸控動作為ACTION_UP會呼叫onClick方法。

ViewGroup的事件分發機制

  1. ViewGroup的定義
    Android中任何控制元件都是直接或者間接整合View的,ViewGroup也是一樣,ViewGroup可以簡單理解成一組View的集合,它裡面既可以包含View,也可以包含ViewGroup,譬如說我們熟悉的LinearLayout、RelativeLayout佈局就是ViewGroup的子類。
  2. ViewGroup的事件分發舉例
    1、MyLayout繼承LinaerLayout + 兩個Button + 設定監聽
myLayout.setOnTouchListener(new OnTouchListener() {  
    @Override  
    public boolean onTouch(View v, MotionEvent event) {  
        Log.d("TAG", "myLayout on touch");  
        return false;  
    }  
});  
button1.setOnClickListener(new OnClickListener() {  
    @Override  
    public void onClick(View v) {  
        Log.d("TAG", "You clicked button1");  
    }  
});  
button2.setOnClickListener(new OnClickListener() {  
    @Override  
    public void onClick(View v) {  
        Log.d("TAG", "You clicked button2");  
    }  
});  

2、分別點選的結果為:
這裡寫圖片描述
即當點選按鈕的時候,MyLayout註冊的onTouch方法並不會執行,只有點選空白區域的時候才會執行該方法。
可以先理解成Button的onClick方法將事件消費掉了,因此事件不會再繼續向下傳遞。
3、ViewGroup中有一個onInterceptTouchEvent方法

public boolean onInterceptTouchEvent(MotionEvent ev) {  
    return false;  
} 

如果重寫這個方法,返回true的話執行結果為:
這裡寫圖片描述
3. ViewGroup事件分發的流程
1、Android中touch事件的傳遞,絕對是先傳遞到ViewGroup,再傳遞到View的
2、當你點選了某個控制元件,首先會去呼叫該控制元件所在ViewGroup的dispatchTouchEvent方法,然後在佈局的dispatchTouchEvent方法中找到被點選的相應控制元件,再去呼叫該控制元件的dispatchTouchEvent方法。
3、其中會有一個onInterceptTouchEvent方法對事件傳遞進行攔截,如果返回值為true的話就表示事件不往子View中傳遞,如果為false的話就表示不對事件傳遞進行攔截,事件會往子View中傳遞

Android事件分發機制大總結

  1. Android中的控制元件都是直接或者間接繼承View的,Viewgroup也是繼承View的,ViewGroup中可以包含View,也可以包含ViewGroup,我們平時接觸的譬如說LinearLayout啊、RelativeLayout就是ViewGroup的子類。
  2. Android的事件分發機制我有看過它的原始碼,總的來說就是Android中觸控事件的傳遞都是先傳遞到ViewGroup,再傳遞到View的。我就舉Button點選這個例子來講解一下Android中觸控事件分發的大致流程吧。
  3. 當點選Button的時候,會呼叫這個控制元件所在佈局的dispatchTouchEvent(),然後在這個佈局中dispatchTouchEvent()方法中找到被點選控制元件的dispatchTouchEvent()方法。
  4. 在呼叫被點選控制元件的dispatchTouchEvent()方法之前會有一次觸控事件的攔截判斷,如果觸控事件被攔截了,就不會再去執行被點選控制元件的dispatchTouchEvent函數了,也就不會再執行onClick點選事件了。而是執行ViewGroup控制元件中的dispatchTouchEvent()的onTouch觸控事件然後返回。
  5. 如果觸控事件沒被攔截的話又是怎麼做呢,就會ViewGroup中dispatchTouchEvent()方法中被點選控制元件的dispatchTouchEvent()方法,就不會執行ViewGroup中的onTouch方法了。
  6. 以上只是闡述了touch事件在ViewGroup中和View中的事件分發過程,但是具體得在一個View中的touch事件分發機制又是怎麼樣的呢,我們繼續往下看
  7. android裡面當觸控到任何一個控制元件的時候就一定會呼叫這個控制元件的dispatchTouchEvent方法。dispatchTouchEvent方法中的原始碼首先會呼叫onTouch方法,不過這個方法要執行的話也需要有兩個前提條件,一個是這個控制元件註冊了觸控監聽、第二個是這個控制元件的狀態要是enabled的。
  8. 執行完onTouch方法之後,會有一個返回值,如果返回這為true的話代表這個點選事件不繼續往下傳遞了,為false的話就表示點選事件繼續往下傳遞,就會執行onTouchEvent方法,onClick方法就是在onTouchEvent中被呼叫的。
  9. 這樣的話一個控制元件的觸控事件在ViewGroup以及View中的分發過程就完成了。