Android 事件攔截

概念介紹

1、onInterceptTouchEvent()是用于處理事件(重點(diǎn)onInterceptTouchEvent這個(gè)事件是從父控件開(kāi)始往子控件傳的菜拓,直到有攔截或者到?jīng)]有這個(gè)事件的view沐飘,然后就往回從子到父控件矛紫,這次是onTouch的)(類似于預(yù)處理仁热,當(dāng)然也可以不處理)并改變事件的傳遞方向耙厚,也就是決定是否允許Touch事件繼續(xù)向下(子控件)傳遞参歹,一但返回True(代表事件在當(dāng)前的viewGroup中會(huì)被處理)仰楚,則向下傳遞之路被截?cái)啵ㄋ凶涌丶](méi)有機(jī)會(huì)參與Touch事件),同時(shí)把事件傳遞給當(dāng)前的控件的onTouchEvent()處理;返回false僧界,則把事件交給子控件的onInterceptTouchEvent()

2侨嘀、onTouchEvent()用于處理事件(重點(diǎn)onTouch這個(gè)事件是從子控件回傳到父控件的,一層層向下傳)捂襟,返回值決定當(dāng)前控件是否消費(fèi)(consume)了這個(gè)事件飒炎,也就是說(shuō)在當(dāng)前控件在處理完Touch事件后,是否還允許Touch事件繼續(xù)向上(父控件)傳遞笆豁。返回false郎汪,則向上傳遞給父控件,詳細(xì)一點(diǎn)就是這個(gè)touch事件就給了父控件闯狱,那么后面的up事件就是到這里touch觸發(fā)煞赢,不會(huì)在傳給它的子控件。如果父控件依然是false哄孤,那touch的處理就給到父控件的父控件照筑,那么up的事件處理都在父控件的父控件,不會(huì)觸發(fā)下面的瘦陈。

返回true凝危,如果是子控件返回true,那么它的touch事件都在這里處理晨逝,父控件是處理不了蛾默,因?yàn)樗詹坏阶涌丶鹘o他的touch,被子控件給攔截了捉貌。(這里啰嗦了這么多就是為了加深記憶支鸡,這個(gè)兩個(gè)事件理解起來(lái)都這么麻煩了,更何況去記趁窃,記我肯定是一下子就忘的了^0^)

(注:可能你會(huì)覺(jué)得是否消費(fèi)了有關(guān)系嗎牧挣,反正我已經(jīng)針對(duì)事件編寫(xiě)了處理代碼?答案是有區(qū)別醒陆!比如ACTION_MOVE或者ACTION_UP發(fā)生的前提是一定曾經(jīng)發(fā)生了ACTION_DOWN瀑构,如果你沒(méi)有消費(fèi)ACTION_DOWN,那么系統(tǒng)會(huì)認(rèn)為ACTION_DOWN沒(méi)有發(fā)生過(guò)刨摩,所以ACTION_MOVE或者ACTION_UP就不能被捕獲寺晌。)

詳細(xì)介紹

onInterceptTouchEvent()是ViewGroup的一個(gè)方法,目的是在系統(tǒng)向該ViewGroup及其各個(gè)childView觸發(fā)onTouchEvent()之前對(duì)相關(guān)事件進(jìn)行一次攔截码邻,Android這么設(shè)計(jì)的想法也很好理解折剃,由于ViewGroup會(huì)包含若干childView,因此需要能夠統(tǒng)一監(jiān)控各種touch事件的機(jī)會(huì),因此純粹的不能包含子view的控件是沒(méi)有這個(gè)方法的像屋,如LinearLayout就有,TextView就沒(méi)有边篮。

onInterceptTouchEvent()使用也很簡(jiǎn)單己莺,如果在ViewGroup里覆寫(xiě)了該方法奏甫,那么就可以對(duì)各種touch事件加以攔截。但是如何攔截凌受,是否所有的touch事件都需要攔截則是比較復(fù)雜的阵子,touch事件在onInterceptTouchEvent()和onTouchEvent以及各個(gè)childView間的傳遞機(jī)制完全取決于onInterceptTouchEvent()和onTouchEvent()的返回值。并且胜蛉,針對(duì)down事件處理的返回值直接影響到后續(xù)move和up事件的接收和傳遞挠进。

關(guān)于返回值的問(wèn)題,基本規(guī)則很清楚誊册,如果return true,那么表示該方法消費(fèi)了此次事件领突,如果return false,那么表示該方法并未處理完全案怯,該事件仍然需要以某種方式傳遞下去繼續(xù)等待處理君旦。

onInterceptTouchEvent()是ViewGroup的一個(gè)方法,目的是在系統(tǒng)向該ViewGroup及其各個(gè)childView觸發(fā)onTouchEvent()之前對(duì)相關(guān)事件進(jìn)行一次攔截嘲碱。

down事件首先會(huì)傳遞到onInterceptTouchEvent()方法金砍。

如果該ViewGroup的onInterceptTouchEvent()在接收到down事件處理完成之后return false,那么后續(xù)的move, up等事件將繼續(xù)會(huì)先傳遞給該ViewGroup麦锯,之后才和down事件一樣傳遞給最終的目標(biāo)view的onTouchEvent()處理恕稠。

如果該ViewGroup的onInterceptTouchEvent()在接收到down事件處理完成之后return true,那么后續(xù)的move, up等事件將不再傳遞給該ViewGroup的onInterceptTouchEvent()扶欣,而是和down事件一樣傳遞給該ViewGroup的onTouchEvent()處理谱俭,注意,目標(biāo)view將接收不到任何事件宵蛀。(這里的意思是說(shuō)昆著,只要被攔截了,當(dāng)前onInterceptTouchEvent()方法將不會(huì)再被回調(diào))

如果最終需要處理事件的view的onTouchEvent()返回了false术陶,那么該事件將被傳遞至其上一層次的view的onTouchEvent()處理凑懂。

如果最終需要處理事件的view 的onTouchEvent()返回了true,那么后續(xù)事件將可以繼續(xù)傳遞給該view的onTouchEvent()處理梧宫。(比如我down事件返回了true,那我的move邏輯將會(huì)被接下來(lái)調(diào)用接谨,如果move返回true,那么繼續(xù)up,如果move返回false,那么就傳遞給上一層次View的onTouchEvent()處理)塘匣。

僅僅看這個(gè)官方文檔解釋脓豪,就能理解清楚這兩個(gè)函數(shù)關(guān)系以及用途的絕對(duì)是富有經(jīng)驗(yàn)的framework高手。

否則忌卤,一定需要一個(gè)案例來(lái)闡釋扫夜。假設(shè)我們有這樣一個(gè)layout,用一個(gè)示例圖來(lái)解釋這個(gè)layout:

通常外圍的layoutview1,layoutview2,只是布局的容器不需要響應(yīng)觸屏的點(diǎn)擊事件,僅僅Mytextview需要相應(yīng)點(diǎn)擊笤闯。但這只是一般情況堕阔,一些特殊的布局可能外圍容器也要響應(yīng),甚至不讓里面的mytextview去響應(yīng)颗味。更有特殊的情況是超陆,動(dòng)態(tài)更換響應(yīng)對(duì)象产还。

那么首先看一下默認(rèn)的觸屏事件的在兩個(gè)函數(shù)之間的傳遞流程剥悟。如下圖:

如果僅僅想讓MyTextView來(lái)響應(yīng)觸屏事件,讓MyTextView的OnTouchEvent返回true,那么事件流就變成如下圖晴玖,可以看到layoutview1,layoutview2已經(jīng)不能進(jìn)入OnTouchEvent:

另外一種情況晶默,就是外圍容器想獨(dú)自處理觸屏事件谨娜,那么就應(yīng)該在相應(yīng)的onInterceptTouchEvent函數(shù)中返回true,表示要截獲觸屏事件,比如layoutview1作截獲處理荤胁,處理流變成如下圖:

以此類推瞧预,我們可以得到各種具體的情況,整個(gè)layout的view類層次中都有機(jī)會(huì)截獲仅政,而且能看出來(lái)外圍的容器view具有優(yōu)先截獲權(quán)垢油。

當(dāng)我們?nèi)プ鲆恍┫鄬?duì)來(lái)講具有更復(fù)雜的觸屏交互效果的應(yīng)用時(shí)候,經(jīng)常需要?jiǎng)討B(tài)變更touch event的處理對(duì)象圆丹,比如launcher待機(jī)桌面和主菜單(見(jiàn)下圖)滩愁,從滑動(dòng)屏幕開(kāi)始到停止滑動(dòng)過(guò)程當(dāng)中,只有外圍的容器view才可以處理touch event,否則就會(huì)誤點(diǎn)擊上面的應(yīng)用圖標(biāo)或者widget.反之在靜止不動(dòng)的狀態(tài)下則需要能夠響應(yīng)圖標(biāo)(子view)的touch事件辫封。摘取framework中abslistview代碼如下

publicbooleanonInterceptTouchEvent(MotionEventev){

intaction=ev.getAction();

switch(action&MotionEvent.ACTION_MASK){

caseMotionEvent.ACTION_DOWN:{

if(touchMode==TOUCH_MODE_FLING){

returntrue;//fling狀態(tài)硝枉,截獲touch,因?yàn)樵诨瑒?dòng)狀態(tài)倦微,不讓子view處理

}

break;

}

caseMotionEvent.ACTION_MOVE:{

switch(mTouchMode){

caseTOUCH_MODE_DOWN:

finalintpointerIndex=ev.findPointerIndex(mActivePointerId);

finalinty=(int)ev.getY(pointerIndex);

if(startScrollIfNeeded(y-mMotionY)){

returntrue;//開(kāi)始滑動(dòng)狀態(tài)妻味,截獲touch事件,不讓子view處理

}

break;

}

break;

}

}

總結(jié):

僅僅通過(guò)概覽性的官方文檔是很難理解onInterceptTouchEvent函數(shù)的用途的欣福,只有通過(guò)演繹這個(gè)抽象的規(guī)則责球,配以圖文才能獲取這個(gè)重要的知識(shí)。很顯然拓劝,默認(rèn)是返回false,不做截獲雏逾。返回true之后,事件流的后端控件就沒(méi)有機(jī)會(huì)處理touch事件了郑临,把默認(rèn)的事件流中每個(gè)處理函數(shù)看作一個(gè)節(jié)點(diǎn)栖博,這個(gè)節(jié)點(diǎn)只要返回true, 后續(xù)的事件就被截止了,這樣想就很好理解厢洞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仇让,一起剝皮案震驚了整個(gè)濱河市典奉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妹孙,老刑警劉巖秋柄,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件获枝,死亡現(xiàn)場(chǎng)離奇詭異蠢正,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)省店,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門嚣崭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人懦傍,你說(shuō)我怎么就攤上這事雹舀。” “怎么了粗俱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵说榆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我寸认,道長(zhǎng)签财,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任偏塞,我火速辦了婚禮唱蒸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灸叼。我一直安慰自己神汹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布古今。 她就那樣靜靜地躺著屁魏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捉腥。 梳的紋絲不亂的頭發(fā)上氓拼,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音但狭,去河邊找鬼披诗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛立磁,可吹牛的內(nèi)容都是我干的呈队。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼唱歧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼宪摧!你這毒婦竟也來(lái)了粒竖?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤几于,失蹤者是張志新(化名)和其女友劉穎蕊苗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體沿彭,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朽砰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喉刘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞧柔。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖睦裳,靈堂內(nèi)的尸體忽然破棺而出造锅,到底是詐尸還是另有隱情,我是刑警寧澤廉邑,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布哥蔚,位于F島的核電站,受9級(jí)特大地震影響蛛蒙,放射性物質(zhì)發(fā)生泄漏糙箍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一宇驾、第九天 我趴在偏房一處隱蔽的房頂上張望倍靡。 院中可真熱鬧,春花似錦课舍、人聲如沸塌西。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)捡需。三九已至,卻和暖如春筹淫,著一層夾襖步出監(jiān)牢的瞬間站辉,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工损姜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饰剥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓摧阅,卻偏偏與公主長(zhǎng)得像汰蓉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棒卷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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