(四)Android事件分發(fā)機制 - 總結(jié)篇

Android事件分發(fā)中三個重要方法:

public boolean dispatchTouchEvent(MotionEvent event)

dispatchTouchEvent用來進行事件的分發(fā)。如果事件能夠傳遞給當(dāng)前的View,那么此方法一定會被調(diào)用,返回結(jié)果表示是否分發(fā)當(dāng)前事件。

public boolean onInterceptTouchEvent(MotionEvent ev)

onInterceptTouchEventViewGroup提供的方法,返回結(jié)果表示是否攔截當(dāng)前事件(默認(rèn)返回false),如果當(dāng)前View攔截了某個事件,那么在同一個事件序列當(dāng)中,此方法不會被再次調(diào)用,

public boolean onTouchEvent(MotionEvent event)

onTouchEventdispatchTouchEvent方法中被調(diào)用,用來處理點擊事件,返回結(jié)果表示是否消耗當(dāng)前事件(默認(rèn)返回true),如果不消耗,則在同一個事件序列中,當(dāng)前View無法再次接受到事件。

三個方法的分布情況:

閱讀Android事件分發(fā)的源代碼(6.0版本)

  • 一個事件序列是指從手指觸摸屏幕開始,到手指離開屏幕結(jié)束,這個過程中產(chǎn)生的一系列事件。同一個事件序列是以ACTION_DOWN事件開始,中間含有數(shù)量不定的ACTION_MOVE事件,最終以ACTION_UP事件結(jié)束;
  • 事件傳遞的順序是:Activity -> Window -> View,即事件總是先傳遞給Activity,然后在傳遞給Window,最后在傳遞給View,頂級View接收到事件后,就會按照事件分發(fā)機制去分發(fā)事件;
  • 事件的傳遞過程是由外向內(nèi)的,即事件總是由父元素分發(fā)給子元素;
  • 正常情況下,一個事件序列只能被一個View攔截且消耗。一旦一個View攔截了某次事件,那么同一個事件序列內(nèi)的所有事件都會直接交給它處理,因此同一個事件序列中的事件不能分別由兩個View同時處理,但是通過特殊手段可以做到,比如一個View將本該自己處理的事件通過onTouchEvent強行傳遞給其他View處理;
  • 某個View一旦開始處理事件,如果它不消耗ACTION_DOWN事件,那么同一事件序列的其他事情都不會再交給它來處理,并且事件將重新交給它的父容器去處理(調(diào)用父容器的onTouchEvent方法);
  • 某個View一旦開始處理事件,如果它消耗ACTION_DOWN事件,但是不消耗其他類型事件,那么這個點擊事件會消失,父容器的onTouchEvent方法不會被調(diào)用,當(dāng)前view依然可以收到后續(xù)的事件,但是這些事件最后都會傳遞給Activity處理;
  • 點擊事件分發(fā)是到達(dá)頂級View后(一般是ViewGroup),會首先調(diào)用dispatchTouchEvent方法,其中它的onInterceptTouchEvent方法如果返回true,則會對事件傳遞進行攔截,事件由ViewGroup處理;如果onInterceptTouchEvent方法返回false,則代表不對事件進行攔截(默認(rèn)返回false),此時子View中的dispatchTouchEvent方法將被調(diào)用,到此,事件已經(jīng)由頂級View傳遞給了下一層的View,接下來的過程是一個遞歸循環(huán)的過程,和頂級View事件分發(fā)過程是一致的,直到完成整個事件分發(fā)。

事件分發(fā)的具體應(yīng)用示例:

Android不規(guī)則點擊區(qū)域詳解


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容