Android 事件分發(fā)機(jī)制

基礎(chǔ)知識(shí)點(diǎn):

對(duì)于觸屏手機(jī),我們?cè)谏厦孢M(jìn)行的任何點(diǎn)擊、滑動(dòng),也就是觸屏(Touch)活動(dòng),都會(huì)生成被封裝到一種叫MotionEvent的事件里,Android系統(tǒng)用一下六種類型來描述用戶的touch事件類型

ACTION_DOWN(按下)

ACTION_MOVE(屏幕滑動(dòng))

ACTION_UP(離開屏幕)

ACTION_POINTER_DOWN(多點(diǎn)觸屏?xí)r產(chǎn)生,暫不講解)

ACTION_POINTER_UP(多點(diǎn)觸屏?xí)r產(chǎn)生,暫不講解)

ACTION_CANCEL

MotionEvent里面包含豐富的數(shù)據(jù)信息,包括:Touch的位置(Touch location),Touch的觸點(diǎn)數(shù)(也即手指數(shù)),Touch的時(shí)刻等等

一個(gè)完整的手勢(shì)(gesture)是以action_down開始,以action_up結(jié)束

事件流:action_down--->action_move--->action_move--->action_move.....--->action_up(中間的action_move事件是否發(fā)生取決于手勢(shì)是否發(fā)生移動(dòng))

想想你平常在桌面點(diǎn)擊打開app和頁面切換滑動(dòng)時(shí)激發(fā)的事件流是否有所不同?

事件的分發(fā),攔截,響應(yīng)的機(jī)制(關(guān)鍵字:分發(fā),攔截,響應(yīng),消費(fèi))

想象:想象一下貪官貪污的一種情況:在某某貧困縣,每年國家都會(huì)給予一定的資金補(bǔ)助(分發(fā)過程),這筆錢(touch事件)經(jīng)過省政府(根布局),市政府(父布局)都沒人去貪污它(即沒人去攔截它),那么這錢就繼續(xù)往下分發(fā),到了縣政府這里來,此時(shí)某某縣大領(lǐng)導(dǎo)(子view)想吃下這筆錢,那么他就不讓這錢逃過他的手了,所以他進(jìn)行了攔截,攔截下來后,就要對(duì)這錢進(jìn)行“處理”呀,這時(shí)就進(jìn)行了響應(yīng)和消費(fèi),以后只要這官不被抓,那么每年國家撥下來的資金都分發(fā)到他這里就被攔截及消費(fèi)了。當(dāng)然還有另外一種情況(現(xiàn)實(shí)不大可能發(fā)生),就是整個(gè)過程沒有人貪污,那么錢就一步一步分發(fā)下去,發(fā)到縣以后,這些年貧困縣發(fā)展起來了,決定不要這筆錢了(響應(yīng)但不消費(fèi)),所以就把錢還給市政府,市政府也決定不要這錢(響應(yīng)但不消費(fèi)),就又把錢交給省政府了

事件分發(fā)流程:從父布局到子布局:Activity--->RootView--->ViewGroup1--->ViewGroup1的子ViewGroup2 ---> Target View

事件的響應(yīng)流程:從子布局到父布局:Target View--->ViewGroup2--->ViewGroup1--->RootView--->activity



幾個(gè)規(guī)則:

所有的事件從activity的dispatchTouchevent()函數(shù)開始,從父布局到子布局往下分發(fā),當(dāng)然每個(gè)布局在任何事件傳到它那里后都可進(jìn)行攔截

所有的事件順著界面布局層次往下分發(fā),分發(fā)完就回溯(上面的分發(fā)和響應(yīng)流程),這一過程中一旦出現(xiàn)了消費(fèi),流程就停在消費(fèi)的view那一層,view必須把a(bǔ)ction_down事件消費(fèi)掉后,后續(xù)的這個(gè)手勢(shì)的其他的事件才會(huì)傳到這個(gè)view。

如果整個(gè)過程沒有view想消費(fèi)這個(gè)事件,那么最終的回溯的結(jié)束點(diǎn)就是activity的onTouchEvent()。

幾個(gè)涉及的重要方法(view或viewgroup里的方法):

public boolean dispatchTouchEvent(Motion ev):事件分發(fā)方法,把當(dāng)前事件分發(fā)給下一子布局,是一個(gè)遞歸的調(diào)用函數(shù),返回true則表示事件被處理

public boolean onInterceptTouchEvent(MotionEvent event):事件攔截方法,根據(jù)事件類型進(jìn)行攔截,比如一個(gè)scrollview想攔截action_move這個(gè)事件,返回true則表示進(jìn)行了攔截

public boolean onTouchEvent(MotionEvent event):事件響應(yīng)處理方法,可以在方法中把事件消費(fèi)了,也可不消費(fèi),那么就回溯給上級(jí)去響應(yīng)和處理,返回true則表示事件被消費(fèi)

整個(gè)分發(fā)和響應(yīng)過程的規(guī)則可以用以下的偽代碼(摘自《Android開發(fā)藝術(shù)探索》)表示:

public boolean dispatchTouchEvent(MotionEvent event){

? ? ?boolean consume=false;

? ? ?if(onInterceptTouchEvent(event)){

? ? ? ? ? ?consume=onTouchEvent(event);

? ? ?} else {?

? ? ? ? ? ?consume=ChildView.dispatchTouchEvent(event);

? ? ?}

? ? ?return consume;

}

以下根據(jù)實(shí)例講述過程:本截圖引用自全英文檔http://trinea.github.io/download/pdf/android/PRE_andevcon_mastering-the-android-touch-system.pdf



講解:此布局是在frameLayout里面嵌套一個(gè)普通的view,當(dāng)你按下的時(shí)候,會(huì)觸發(fā)down事件,事件就從activity出發(fā),由于此時(shí)沒有任何的布局對(duì)此感興趣(即沒攔截和消費(fèi)),那么分發(fā)完后回溯會(huì)activity的onTouchEvent,后續(xù)發(fā)生的move和up事件,這時(shí)Android系統(tǒng)會(huì)這么認(rèn)為:既然你整個(gè)布局所有組件連按下去的事件都不感興趣,后續(xù)發(fā)生的事件肯定也是不感興趣,所以事件move和up都不往下進(jìn)行分發(fā)和回溯了,直接在activity自己調(diào)用onTouchEvent去處理


講解:此布局是在frameLayout里面嵌套一個(gè)button,當(dāng)你按下的時(shí)候,會(huì)觸發(fā)down事件,事件就從activity出發(fā),由于此時(shí)button對(duì)此事件感興趣,那么button的onTouchEvent就會(huì)對(duì)此進(jìn)行消費(fèi),事件被消費(fèi)后就不會(huì)再回溯了,后續(xù)發(fā)生的move和up事件,button也是感興趣,也進(jìn)行了消費(fèi),所以整個(gè)流程就只走到了button的onTouchEvent方法


講解:此布局是在Scrollview里面嵌套一個(gè)button,當(dāng)你按下的時(shí)候,會(huì)觸發(fā)down事件,事件就從activity出發(fā),由于此時(shí)button對(duì)此事件感興趣,而scrollView對(duì)此事件不感興趣,那么button的onTouchEvent就會(huì)對(duì)此進(jìn)行消費(fèi),事件被消費(fèi)后就不會(huì)再回溯了,后續(xù)發(fā)生的move和up事件,scrollview和button都感興趣,但是由于scrollview先拿到事件,進(jìn)行攔截和消費(fèi),所以事件流就沒走到button那里,那為什么還會(huì)走回activity的onTouchEvent呢,scrollview進(jìn)行攔截,但不進(jìn)行消費(fèi),也就是scrollview的onTouchEvent返回值是false,所以才會(huì)回溯給activity。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容