1. 程式人生 > >android的事件分發傳遞機制

android的事件分發傳遞機制

      事件的分發與傳遞最重要的三個處理方法是

             dispatchTouchEvent

             onInterceptTouchEvent            

             onTouchEvent

 

1 , 事件分發:public boolean dispatchTouchEvent(MotionEvent ev)

    Touch事件發生時Activity的dispatchTouchEvent(MotionEvent ev)方法會將事件傳遞給最外層View的dispatchTouchEvent(MotionEvent ev)方法,該方法對事件進行分發。分發邏輯如下:
    如果return true,事件會由當前View的dispatchTouchEvent方法進行消費,同時事件會停止向下傳遞;

    如果return false,事件分發分為兩種情況:
      如果當前 View 獲取的事件直接來自 Activity,則會將事件返回給Activity的onTouchEvent進行消費;
      如果當前 View 獲取的事件來自外層父控制元件,則會將事件返回給父View的onTouchEvent進行消費。

    如果return super.dispatchTouchEvent(ev),事件分發分為兩種情況:

     如果當前View是ViewGroup,則事件會分發給onInterceptTouchEvent方法進行處理;

     如果當前View是普通View,則事件直接交給onTouchEvent方法進行處理

   2, 事件攔截:public boolean onInterceptTouchEvent(MotionEvent ev)

   此方法只有ViewGroup才有, Activity與普通View沒有。上面已經提到,如果當前ViewGroup的dispatchTouchEvent(事件分發)返回super.dispatchTouchEvent(ev), 那麼事件會傳遞到傳遞到       onInterceptTouchEvent方法, 該方法對事件進行攔截。攔截邏輯如下:
    如果return true,則表示攔截該事件,並將事件交給當前View的onTouchEvent方法;

    如果return false,則表示不攔截該事件,並將該事件交由子View的dispatchTouchEvent方法進行事件分發,重複上述過程;

    如果return super.onInterceptTouchEvent(ev), 事件攔截分兩種情況:       

       如果該View(ViewGroup)存在子View且點選到了該子View, 則不攔截, 繼續分發給子View 處理, 此時相當於return false。

     如果該View(ViewGroup)沒有子View或者有子View但是沒有點選中子View(此時ViewGroup相當於普通View), 則交由該View的onTouchEvent響應,此時相當於return true。 

一般的LinearLayout、 RelativeLayout、FrameLayout等ViewGroup預設不攔截, 而ScrollView、ListView等ViewGroup則可能攔截,得看具體情況。

   3, 事件響應:public boolean onTouchEvent(MotionEvent ev)

    上面已經提到,在dispatchTouchEvent(事件分發)返回super.dispatchTouchEvent(ev)並且onInterceptTouchEvent進行攔截(事件攔截返回true)的情況下,那麼事件會傳遞到onTouchEvent       方法,該方法對事件進行響應。響應邏輯如下:
    如果return true,則表示響應並消費該事件;
    如果return fasle,則表示不響應事件,那麼該事件將會不斷向上層View的onTouchEvent方法傳遞,直到某個View的onTouchEvent方法返回true,如果到了最頂層View還是返回false,那麼認為該事件不消耗,則在同一個事件系列中,當前View無法再次接收到事件,該事件會交由Activity的onTouchEvent進行處理;
    如果return super.dispatchTouchEvent(ev),事件處理分為兩種情況:

    如果該View是clickable或者longclickable的,則會返回true, 表示消費了該事件, 與返回true一樣;

    如果該View不是clickable或者longclickable的,則會返回false, 表示不消費該事件,將會向上傳遞,與返回false一樣.

 

   如下流程圖: