[Android]點擊事件的傳遞,從ViewGroup到View傳遞簡短總結

簡單的點擊事件處理是很容易的,要明白傳遞的流程有點困難,LZ研究事件傳遞的過程中被弄混了許多次,所以總結一下經驗,順便整理一下思路,幫助記憶。


一個佈局文件,如果只有單個按鈕,設置點擊事件是不需要再說了。

   <span style="white-space:pre">	</span><Button
        android:id="@id/btn"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

如果佈局文件包括ViewGroup(如RelativeLayout)和VIew(如Button),那麼就可以研究一下事件傳遞和處理的順序。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <Button
        android:id="@id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>
將RelativeLayout看成最底層的佈局,Button看成最高層的。


最底層的佈局開始,RelativeLayout調用其dispathTouchEvent()方法(可以在父類ViewGroup中找到源碼)。從方法名或者註釋可以看出,這個是分發事件的意思。

根據dispathTouchEvent()的返回值:

1.true,已處理,不會向上傳遞,已經將事件分發給RelativeLayout;

2.false,未處理,繼續向上傳遞;


如果返回的是false,則繼續調用onInterceptTouchEvent(MotionEvent ev)。

從方法名或者註釋可以看出,這個是攔截事件的意思。

該方法默認返回false,可通過重寫改變其返回值。

根據其返回值的不同:

1.true,已處理,不會向上傳遞,等於將事件攔截;

2.false,未處理,繼續向上傳遞,沒有攔截;


需要注意的是,如果上述兩個方法有其中一個返回true,再有點擊事件的時候,就不會再進行判斷,而是直接給其onTouch()方法處理。


接下來事件就傳遞到View部分,也就是Button。


同樣的,Button首先調用的也是dispathTouchEvent()

根據dispathTouchEvent()的返回值:

1.true,已處理,不會向上傳遞;

2.false,未處理,繼續向上傳遞;


繼續到onTouchEvent(),也是根據返回值判斷

1.true,已處理,不會向上傳遞;

2.false,未處理,繼續向傳遞;

這裏返回false會將事件重新傳遞給ViewGroup(RelativeLayout),調用其onTouch  ()方法,根據返回值:

1.true,已處理,不會向上傳遞;

2.false,事件沒有被消費;


需要注意的是,到這裏傳遞事件基本就結束了,如果事件沒有被消費掉,將被Activity外部處理掉,也就不再需要關心了。


最後說明,無論是響應什麼動作,都要先從 ACTION_DOWN事件開始的,如果  ACTION_DOWN沒有被處理,那麼接下來的其他都不會被處理。



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