View事件分發(fā)(一)

View事件分發(fā)

點擊事件的傳遞規(guī)則

點擊事件首先要分析的對象就是MotionEvent式廷,即點擊事件,其實所謂的點擊事件的事件的华弓,其實就是對MotionEvent事件的分發(fā)過程食零,即當(dāng)一個MotionEvent產(chǎn)生之后,系統(tǒng)需要把這號事件傳遞給一個具體的View寂屏,而這個傳遞的過程就是View的事件分發(fā)過程贰谣。
  其中,點擊事件的分發(fā)過程由三個方法共同完成:dispatchTouchEvent迁霎,onInterceptTouchEvent吱抚,onTouchEvent

以下要注意消耗攔截的區(qū)別

dispatchTouchEvent

public boolean dispatchTouchEvent(MotionEvent event)
  用來進(jìn)行事件的分開考廉,如果事件可以傳遞到當(dāng)前的View中秘豹,那么這個方法一定會被調(diào)用,返回結(jié)果受當(dāng)前View的onTouchEvent和下級View的dispatchTouchEvent的影響昌粤,表示是否消耗當(dāng)前事件既绕。

onInterceptTouchEvent

public boolean onInterceptTouchEvent(MotionEvent event)
  在dispatchTouchEvent方法內(nèi)部調(diào)用啄刹,用于判斷是否攔截某個事件,如果當(dāng)前View攔截了某個事件凄贩,那么在同一個事件序列中誓军,這個方法不會被再次調(diào)用,返回結(jié)果表示是否攔截當(dāng)前事件疲扎。

onTouchEvent

public boolean onTouchEvent(MotionEvent event)
  在dispatchTouchEvent方法內(nèi)部調(diào)用昵时,用來處理點擊事件,返回結(jié)果表示是否消耗當(dāng)前事件评肆,如果不消耗,則在同一個事件序列內(nèi)非区,當(dāng)前View無法再次接收到事件瓜挽。
 
  以下是它們之間關(guān)系的偽代碼。

public boolean dispatchTouchEvent(MotionEvent event) {
    boolean consume = false;
    if (onInterceptTouchEvent(event)) {
        consume = onTouchEvent(event);
    } else {
        consume = child.dispatchTouchEvent(event);
    }
    
    return consume;
}

上面的代碼可以大概了表現(xiàn)出事件的傳遞規(guī)則:對一個根ViewGroup來說征绸,點擊事件產(chǎn)生后久橙,首先會傳遞給它,這個時候它的dispatchTouchEvent就會被調(diào)用管怠,如果ViewGroup的onInterceptTouchEvent方法返回true淆衷,那么就表示它要攔截當(dāng)前事件,接著這個事件就會交給這個ViewGroup處理渤弛。即它的onTouchEvent會被調(diào)用祝拯;而如果這個ViewGroup的onInterceptTouchEvent方法返回false,那么就表示它不攔截當(dāng)前事件她肯,這個時候當(dāng)前事件就會傳遞給它的子元素佳头,接著子元素的dispatchTouchEvent就會被調(diào)用,如此反復(fù)直至事件被最終處理晴氨。

onTouchListener與onClickListener

當(dāng)一個View需要處理事件時康嘉,如果它設(shè)置了OnTouchListener,那么OnTouchListener中的onTouch方法會被回調(diào)籽前。這時候事件要根據(jù)onTouch方法的返回值進(jìn)行處理亭珍,如果onTouch返回true,那么onTouchEvent方法將不會被調(diào)用枝哄;如果onTouch返回false肄梨,那么onTouchEvent將會被調(diào)用。由此可見挠锥,給View設(shè)置的OnTouchListener峭范,優(yōu)先級比onTouchEvent要高。而在onTouchEvent方法中瘪贱,如果當(dāng)前設(shè)置的有onClickListener,那么它的onClick方法會被調(diào)用纱控,由此可見辆毡,onClickListener優(yōu)先級最低。

點擊事件的傳遞順序

當(dāng)一個點擊事件產(chǎn)生之后甜害,它的傳遞過程遵循如下順序:Activity->Window->View舶掖。事件總是先傳遞給ActivityActivity再傳遞給Window尔店,最后Window再傳遞給DecorView眨攘。當(dāng)DecorView接收到事件后,就會按照事件分發(fā)機制去處理嚣州。
  考慮一種情況鲫售,如果一個View的onTouchEvent返回了false,那么它的父容器的onTouchEvent將會被調(diào)用该肴。以此類推情竹,假如所有的元素都不處理這個事件,那么這個事件最終會交給Activity處理匀哄。

事件傳遞的規(guī)則

對于事件傳遞的機制秦效,以下是其一些規(guī)則,根據(jù)規(guī)則可以更清楚地了解整個流程涎嚼。

  1. 同一個事件序列是指從手指從觸摸屏幕的那一刻起阱州,到手指離開手機的那一刻結(jié)束,在這個過程中產(chǎn)生的一系列事件法梯,這個事件以down事件開始苔货,中間含有數(shù)量不定的move事件,最終以up事件結(jié)束立哑。
  2. 正常情況下蒲赂,一個事件序列只能被一個View攔截消耗,這條原因可以參照3刁憋,因為一旦一個元素攔截了某個事件滥嘴,那么同一個事件序列內(nèi)的所有事件都會直接交給它處理,因此同一個事件序列內(nèi)的事件由兩個View同時處理至耻,但是通過特殊手段可以做到若皱,比如一個View將本該直接自己處理的事件強行傳遞給其他View。
  3. 當(dāng)某個View一旦決定攔截尘颓,那么這一個事件序列都只能由它處理(如果事件序列能夠傳遞給它的話)走触,并且它的onInterceptTouchEvent不會被調(diào)用。也就是說疤苹,當(dāng)View決定攔截一個事件之后互广,系統(tǒng)會把同一個事件序列內(nèi)的其他方法都直接交給它處理,因此就不會再調(diào)用這個View的onInterceptTouchEvent去詢問它是否攔截。
  4. 某個View一旦開始處理事件惫皱,如果它不消耗ACTION_DOWN事件像樊,即onTouchEvent返回了false,那么同一事件序列的其他事件都不會交由它處理旅敷,并且事件將重新交由它的父元素去處理生棍,即父元素的onTouchEvent會被調(diào)用。即事件一旦交給一個View處理媳谁,那么它必須消耗掉涂滴,否則同一事件的剩下的事件就不再交由它處理了。
  5. 如果View不消耗除ACTION_DOWN以外的事件晴音,那么這個點擊事件會消失柔纵,此時父元素的onTouchEvent就不會被調(diào)用,并且當(dāng)前View可以持續(xù)收到后續(xù)的事件锤躁,最后這些消失的事件傳遞給Activity處理搁料。
  6. ViewGroup默認(rèn)不攔截任何事件,Android源碼中的ViewGrouponInterceptTouchEvent默認(rèn)返回false进苍。
  7. View沒有onInterceptTouchEvent方法加缘,一旦有點擊事件傳遞給它鸭叙,那么它的onTouchEvent將會被調(diào)用觉啊。
  8. View的onTouchEvent默認(rèn)都會消耗攔截事件(返回true),除非它是不可點擊的(即clickablelongClickable屬性同時為false)沈贝。View的longClickable屬性默認(rèn)都為false杠人,View的clickable屬性要區(qū)分情況,比如Button的為true宋下,TextView的為false嗡善。
  9. View的enable屬性不影響onTouchEvent的默認(rèn)返回值。只要View的clickable或者longClickable有一個為true学歧,那么它的onTouchEvent返回值就是true罩引。
  10. onClick發(fā)生的前提是當(dāng)前View是可點擊的,并且它收到了downup事件枝笨。
  11. 事件的傳遞過程是由外向內(nèi)的袁铐,事件總是先傳遞給父元素,然后再由父元素傳遞給子View横浑,通過requestDisallowInterceptTouchEvent方法可以在子元素中干預(yù)父元素的分發(fā)過程剔桨,但是ACTION_DOWN事件除外。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末徙融,一起剝皮案震驚了整個濱河市洒缀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖树绩,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萨脑,死亡現(xiàn)場離奇詭異,居然都是意外死亡葱峡,警方通過查閱死者的電腦和手機砚哗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來砰奕,“玉大人蛛芥,你說我怎么就攤上這事【” “怎么了仅淑?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長胸哥。 經(jīng)常有香客問我涯竟,道長,這世上最難降的妖魔是什么空厌? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任庐船,我火速辦了婚禮,結(jié)果婚禮上嘲更,老公的妹妹穿的比我還像新娘筐钟。我一直安慰自己,他們只是感情好赋朦,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布篓冲。 她就那樣靜靜地躺著,像睡著了一般宠哄。 火紅的嫁衣襯著肌膚如雪壹将。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天毛嫉,我揣著相機與錄音诽俯,去河邊找鬼。 笑死承粤,一個胖子當(dāng)著我的面吹牛暴区,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播密任,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼颜启,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了浪讳?” 一聲冷哼從身側(cè)響起缰盏,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后口猜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體负溪,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年济炎,在試婚紗的時候發(fā)現(xiàn)自己被綠了川抡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡须尚,死狀恐怖崖堤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情耐床,我是刑警寧澤密幔,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站撩轰,受9級特大地震影響胯甩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜堪嫂,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一偎箫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧皆串,春花似錦淹办、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽齐遵。三九已至寂玲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梗摇,已是汗流浹背拓哟。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留伶授,地道東北人断序。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像糜烹,于是被迫代替她去往敵國和親违诗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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