講一講 Android 的事件分發(fā)機(jī)制蹭越?

一障本,事件分發(fā)

1,有哪些事件响鹃?

事件 簡介
ACTION_DOWM 手指初次接觸到屏幕時(shí)觸發(fā)
ACTION_MOVE 手指在屏幕上滑動時(shí)觸發(fā)驾霜,會多次觸發(fā)
ACTION_UP 手指離開屏幕時(shí)觸發(fā)
ACTION_CANCEL 事件被上層攔截時(shí)觸發(fā)

2,view 繼承關(guān)系

view 子類 Imgview Textview 等
子類 ViewGroup : LinearLayout买置,RelativeLayout粪糙,ListView,Recyclerview等

繼承自View的只能處理事件忿项,繼承自ViewGroup的才能進(jìn)行分發(fā)事件(先分發(fā)在處理蓉冈,比View多了一個(gè)分發(fā)流程)

2.1,總流程

111.jpg

Activity#dispatchTouchEvent()-》PhineWindow#superDispatchTouchEvent()-》DecorView#superDispatchTouchEvent()
-》ViewGroup#dispatchTouchEvent--》...->View#dispatchTouchEvent ->#onTouchEvent

分發(fā)2.png

2.2轩触, View寞酿,ViewGroup 事件分發(fā),文字解說

  • 2.2.1. ViewGroup 比View 多了一個(gè)事件onInterceptTouchEvent脱柱; ViewGroup 繼承 View 伐弹,dispatchTouchEvent、onTouchEvent
  • 2.2.2.ViewGroup 和 View 組成了一個(gè)樹狀結(jié)構(gòu)榨为,根節(jié)點(diǎn)為 Activity 內(nèi)部包含的一個(gè)ViwGroup惨好。
  • 2.2.3.觸摸事件由 Action_Down煌茴、Action_Move、Aciton_UP 組成日川,其中一次完整的觸摸事件中蔓腐,Down 和 Up 都只有一個(gè),Move 有若干個(gè)龄句,可以為 0 個(gè)合住。
  • 2.2.4.當(dāng) Acitivty 接收到 Touch 事件時(shí),將遍歷子 View 進(jìn)行 Down 事件的分發(fā)撒璧。ViewGroup 的遍歷可以看成是遞歸的透葛。分發(fā)的目的是為了找到真正要處理本次完整觸摸事件的 View,這個(gè) View 會在 onTouchuEvent 結(jié)果返回 true卿樱。
  • 2.2.5.當(dāng)某個(gè)子 View 返回 true 時(shí)僚害,會中止 Down 事件的分發(fā),同時(shí)在 ViewGroup 中記錄該子 View繁调。接下去的 Move 和 Up 事件將由該子 View 直接進(jìn)行處理萨蚕。由于子View是保存在ViewGroup中的,多層ViewGroup的節(jié)點(diǎn)結(jié)構(gòu)時(shí)蹄胰,上級ViewGroup保 存 的 會 是 真 實(shí) 處 理 事 件 的 View 所 在 的 ViewGroup 對 象 : 如ViewGroup0-ViewGroup1-TextView 的結(jié)構(gòu)中岳遥,TextView 返回了 true,它將被保存在 ViewGroup1 中裕寨,而 ViewGroup1 也會返回 true浩蓉,被保存在 ViewGroup0 中。當(dāng)Move 和 UP 事件來時(shí)宾袜,會先從 ViewGroup0 傳遞至 ViewGroup1捻艳,再由 ViewGroup1傳遞至 TextView。
  • 2.2.6.當(dāng) ViewGroup 中所有子 View 都不捕獲 Down 事件時(shí)庆猫,將觸發(fā) ViewGroup 自身的 onTouch 事件认轨。觸發(fā)的方式是調(diào)用 super.dispatchTouchEvent 函數(shù),即父類 View的 dispatchTouchEvent 方法月培。在所有子 View 都不處理的情況下嘁字,觸發(fā) Acitivity 的onTouchEvent 方法。
  • 2.2.7.onInterceptTouchEvent 有兩個(gè)作用:1.攔截 Down 事件的分發(fā)杉畜。2.中止 Up 和 Move事件向目標(biāo) View 傳遞纪蜒,使得目標(biāo) View 所在的 ViewGroup 捕獲 Up 和 Move 事件。

自我一句話總結(jié):ViewGroup 先通過dispatchTouchEvent進(jìn)行分發(fā),中途ViewGroup 有權(quán)不分發(fā)下去(通過onInterceptTouchEvent 返回return true 進(jìn)行攔截)寻行,不攔截情況下 在傳遞到View 的dispatchTouchEvent 霍掺,View若不進(jìn)行消費(fèi)(onTouchEvent )),轉(zhuǎn)給ViewGroup 的 onTouchEvent

可以理解:總經(jīng)理 -》部門經(jīng)理-》組長-》工人; 事件下去過程的分配杆烁,賺錢的項(xiàng)目上級的有權(quán)選擇自己做牙丽;若工人接到任務(wù),能力有限兔魂,同樣也可以交回上級處理烤芦;

疑問:對于上面舉例,要是好事情都被上級攔截析校;那工人豈不造反构罗;利益不均?智玻,一旦分發(fā)到子View遂唧,子View也有方法請求父容器不攔截;

于是可以看下:外部攔截法吊奢、內(nèi)部攔截法

3盖彭,View滑動沖突處理方法(外部攔截法、內(nèi)部攔截法)

引入https://blog.csdn.net/z_l_p/article/details/53488085页滚,思路肯定是對的召边,代碼完不完全對沒有測試過

1、外部攔截法 (子view代碼無需修改)(符合view事件分發(fā)機(jī)制)

說明:需要在父ViewGroup裹驰,重寫onInterceptTouchEvent方法隧熙,根據(jù)業(yè)務(wù)需要,判斷哪些事件是父Viewgroup需要的幻林,需要的話就對該事件進(jìn)行攔截贞盯,然后交由onTouchEvent方法處理,若不需要滋将,則不攔截邻悬,然后傳遞給子view或子viewGroup,
代碼:

public boolean onInterceptTouchEvent(MotionEvent ev) {
    int y= (int) ev.getY();
    switch (ev.getAction()){
        case MotionEvent.ACTION_DOWN:
            yDown=y;
            isIntercept=false;
            break;
        case MotionEvent.ACTION_MOVE:
            yMove=y;
            if (yMove-yDown<0){                    //根據(jù)業(yè)務(wù)需求更改判斷條件症昏,判斷是時(shí)候需要攔截
                isIntercept=false;
            }else if(yMove-yDown>0&&getChildAt(0).getScrollY()==0){
                isIntercept=true;
            }else if(yMove-yDown>0&&getChildAt(0).getScrollY()>0){
                isIntercept=false;
            }
            break;
        case MotionEvent.ACTION_UP:
            isIntercept=false;
            break;
    }
    return isIntercept;         //返回true表示攔截随闽,返回false表示不攔截
}

2、內(nèi)部攔截法(父viewgroup需要重寫onInterceptTouchEvent)(不符合view事件分發(fā)機(jī)制)

個(gè)人理解就是肝谭,攔截前 先判斷子View時(shí)候是否改變過disallowIntercept值 disallowIntercept是true根本不執(zhí)行攔截方法了
 if (!disallowIntercept) {
                    intercepted = onInterceptTouchEvent(ev);
                    ev.setAction(action); // restore action in case it was changed
      } else {
               intercepted = false;
   }

說明:顧名思義就是在子view中攔截事件掘宪,父viewGroup默認(rèn)是不攔截任何事件的,所以攘烛,當(dāng)事件傳遞到子view時(shí)魏滚,
子view根據(jù)自己的實(shí)際情況來,如果該事件是需要子view來處理的坟漱,那么子view就自己消耗處理鼠次,如果該事件不需要由子view來處理,那么就調(diào)用getParent().requestDisallowInterceptTouchEvent()方法來通知父viewgroup來攔截
這個(gè)事件,也就是說腥寇,叫父容器來處理這個(gè)事件成翩,這剛好和view的分發(fā)機(jī)制相反。

代碼: (需要注意赦役,要確保MotionEvent.ACTION_DOWN時(shí)不攔截)

//子view的代碼·
public boolean dispatchTouchEvent(MotionEvent ev) {
    int y= (int) ev.getY();
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            getParent().requestDisallowInterceptTouchEvent(true);
            yDown=y;
            break;
        case MotionEvent.ACTION_MOVE:
            yMove=y;
            Log.e("mes",yMove+"B榈小!掂摔!");
            int scrollY = getScrollY();
            if (scrollY == 0&&yMove-yDown>0) {    //根據(jù)業(yè)務(wù)需求判斷是否需要通知父viewgroup來攔截處理該事件
                //允許父View進(jìn)行事件攔截
                Log.e("mes",yMove-yDown+"攔截");
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        case MotionEvent.ACTION_UP:
            break;
    }
    return super.dispatchTouchEvent(ev);
}
//父viewgroup代碼     (要確保down是不攔截术羔,move和up時(shí)要攔截)
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if(ev.getAction()==MotionEvent.ACTION_DOWN){
        return false;
    }else{
        return true;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市乙漓,隨后出現(xiàn)的幾起案子级历,更是在濱河造成了極大的恐慌,老刑警劉巖叭披,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鱼喉,死亡現(xiàn)場離奇詭異,居然都是意外死亡趋观,警方通過查閱死者的電腦和手機(jī)扛禽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來皱坛,“玉大人编曼,你說我怎么就攤上這事∈1伲” “怎么了掐场?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贩猎。 經(jīng)常有香客問我熊户,道長,這世上最難降的妖魔是什么吭服? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任嚷堡,我火速辦了婚禮,結(jié)果婚禮上艇棕,老公的妹妹穿的比我還像新娘蝌戒。我一直安慰自己,他們只是感情好沼琉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布北苟。 她就那樣靜靜地躺著,像睡著了一般打瘪。 火紅的嫁衣襯著肌膚如雪友鼻。 梳的紋絲不亂的頭發(fā)上傻昙,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音彩扔,去河邊找鬼屋匕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛借杰,可吹牛的內(nèi)容都是我干的过吻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼蔗衡,長吁一口氣:“原來是場噩夢啊……” “哼纤虽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绞惦,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤逼纸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后济蝉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杰刽,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年王滤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贺嫂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡雁乡,死狀恐怖第喳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情踱稍,我是刑警寧澤曲饱,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站珠月,受9級特大地震影響扩淀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜啤挎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一驻谆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧侵浸,春花似錦旺韭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽值漫。三九已至澳腹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酱塔。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工沥邻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人羊娃。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓唐全,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蕊玷。 傳聞我的和親對象是個(gè)殘疾皇子邮利,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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

  • 一、前言: 1. MotionEvent事件 手指接觸屏幕后所產(chǎn)生的事件垃帅,主要有如下幾種: ACTION_DOWN...
    因?yàn)槲业男?/span>閱讀 725評論 0 1
  • 前言: 事件分發(fā)作為android面試必問的面試點(diǎn)延届,我們是很有必要熟練掌握以及理解的,很多時(shí)候我們都知道整個(gè)分發(fā)流...
    yosen閱讀 522評論 0 5
  • 久違的晴天贸诚,家長會方庭。 家長大會開好到教室時(shí),離放學(xué)已經(jīng)沒多少時(shí)間了酱固。班主任說已經(jīng)安排了三個(gè)家長分享經(jīng)驗(yàn)械念。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,496評論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友运悲。感恩相遇订讼!感恩不離不棄。 中午開了第一次的黨會扇苞,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,551評論 0 11
  • 可愛進(jìn)取欺殿,孤獨(dú)成精。努力飛翔鳖敷,天堂翱翔脖苏。戰(zhàn)爭美好,孤獨(dú)進(jìn)取定踱。膽大飛翔棍潘,成就輝煌。努力進(jìn)取崖媚,遙望亦歉,和諧家園〕┭疲可愛游走...
    趙原野閱讀 2,716評論 1 1