Android事件分發機制

Android事件分發機制算是Android高級篇的基礎了,程序猿一定要對其有所瞭解。

(1)確定事件分發的對象

當用戶點擊View或ViewGroup時就產生了觸摸(Touch)事件,Touch相關的細節被封裝成了MotionEvent對象。當我們自定義View時經常重寫onTouchEvent方法,比如:

@Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_MOVE:
            break;
        case MotionEvent.ACTION_CANCEL:
            break;
        case MotionEvent.ACTION_UP:
            break;

    }
    return super.onTouchEvent(event);
}

onTouchEvent可以監聽到觸摸(Touch)事件。

常用的Touch事件有四種:

  • MotionEvent.ACTION_DOWN:按下View
  • MotionEvent.ACTION_MOVE:滑動View
  • MotionEvent.ACTION_CANCEL:非人爲原因取消事件
  • MotionEvent.ACTION_UP:擡起View

View事件的基本流程是:

用戶按下View,觸發ACTION_DOWN事件-->用戶拖動或滾動View,觸發ACTION_MOVE事件-->用戶擡起,放開View,觸發ACTION_UP事件。
ACTION_CANCEL事件的觸發非人爲觸發,也許是程序猿代碼中主動取消,也許是發生了異常導致取消。

(2)事件分發的本質

本質上是將點擊時間的出來傳遞到View本身去處理,這個過程叫做分發過程。

(3)事件傳遞的載體

事件傳遞的載體是:Activity(Window)、ViewGroup、View。

假設點擊一個按鈕,事件的傳遞順序是:Activity(Window)-->ViewGroup-->View

下圖是Activity、ViewGroup、View的層級圖,其實Activity上面還有一層叫PhoneWindow,但不是本章重點。

請先記住觸摸事件的傳遞順序:Activity(Window)-->ViewGroup-->View

  • Activity:它是Android界面的基本
  • ViewGroup:有線性佈局、相對佈局、約束佈局、幀佈局、表格佈局、RecyclerView、其它自定義ViewGroup
  • View:比如,TextView、ImageView或者其它自定義View
(4)事件的分發由哪些方法協調?

事件的分發由dispatchTouchEvent()onInterceptTouchEvent()onTouchEvent()相互協調的。

  • onTouchEvent():負責處理觸摸事件

事件分發到最後,總是由 onTouchEvent()來處理觸摸事件。

它的返回值代表的意義:
[true]:直接結束
[super或false]:執行上級的onTouchEvent()方法

  • dispatchTouchEvent() :負責分發觸摸事件

事件的分發總是由這個方法開始,根據不同的返回值做出相應的處理:
[true]:直接結束事件的分發
[false]:執行上級的onTouchEvent()方法去處理觸摸事件,最後結束事件的分發
[super]:繼續分發事件

  • onInterceptTouchEvent():負責攔截觸摸事件

只有在ViewGroup中才有這個方法,這個方法專門負責事件的攔截工作,根據返回值處理不同的結果:
[true]:執行ViewGroup的onTouchEvent()事件;
[super或false]:執行View的dispatchTouchEvent()方法

(5)事件在Activity中是如何處理的?

前提條件:Activity中有一個按鈕(View),按鈕在一個佈局(ViewGroup)中。

我們都知道觸摸事件的傳遞順序:Activity(Window)-->ViewGroup-->View,那麼在Activity中事件是如何處理的呢?

Activity中有一個dispatchTouchEvent方法,當有觸摸事件時,最先執行的方法就是dispatchTouchEvent,它的返回類型是一個boolean類型,默認情況下返回super.dispatchTouchEvent(ev),當返回super.dispatchTouchEvent(ev)時,事件將傳遞給ViewGroup,但是如果返回true或者false時,事件就會直接結束,不會傳遞給ViewGrou,更不會傳遞給View。

比如,在Activity中重寫dispatchTouchEvent

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    return true;
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    return false;
}

這種情況下,按鈕是不可能監聽到點擊事件的,一般我們不會在Activity中重寫dispatchTouchEvent方法,就默認返回super.dispatchTouchEvent(ev),讓它把事件傳遞到ViewGroup即可。

(6)事件在ViewGroup中是如何處理的?

當事件從Activity傳遞到ViewGroup之後,ViewGroup是如何處理這個事件的呢?

在ViewGroup中,事件首先被分發到ViewGroup的dispatchTouchEvent方法:

  • 如果返回true則直接結束分發;
  • 如果返回false,則執行Activity的onTouchEvent方法,Activity的onTouchEvent方法不管返回什麼都直接結束分發;
  • 如果返回super.dispatchTouchEvent(ev),則執行onInterceptTouchEvent方法;

onInterceptTouchEvent的返回值解析如下:

  • 如果返回true,則執行ViewGroup的onTouchEvent方法;
  • 如果返回super或者false,則執行View的dispatchTouchEvent方法;

onTouchEvent的返回值解析如下:

  • 返回true,直接結束事件
  • 否則,執行Activity的onTouchEvent方法
(7)事件在View中是如何處理的?

在View中,事件首先被分發到View的dispatchTouchEvent方法:

  • 返回true,結束事件
  • 返回false,執行ViewGroup的onTouchEvent方法
  • 返回super,則直接執行View的onTouchEvent方法
(8)事件分發流程圖(是重點,要記住)

以上這張圖要記住,上面說了那麼多廢話,記不住不要緊,只要將這張圖記住就可以了。

(9)總結
  • 請記住以上的一張圖,因爲這張圖纔是世間分發機制的精髓所在,其實這張圖就是事件分發機制的全部了;
  • 事件分發機制是實現自定義View的基礎,所以一定要了解;
  • 現在很多嵌套View都存在觸摸事件衝突問題,這時就需要事件分發機制的知識來解決這個問題了。

[本章完...]

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