安卓事件分發(fā)機制

##事件分發(fā)原理

1 事件分發(fā)的對象是誰郭脂?

????答:事件

當用戶觸摸屏幕時(View或ViewGroup派生的控件)矩屁,將產(chǎn)生點擊事件(Touch事件)拒垃。

Touch事件相關細節(jié)(發(fā)生觸摸的位置僵朗、時間滋将、歷史記錄衔峰、手勢動作等)被封裝成MotionEvent對象

##主要發(fā)生的Touch事件有如下四種:

????MotionEvent.ACTION_DOWN:0佩脊,按下View(所有事件的開始)

????MotionEvent.ACTION_MOVE:2蛙粘,滑動View

????MotionEvent.ACTION_CANCEL:非人為原因結束本次事件

????MotionEvent.ACTION_UP:1,抬起View(與DOWN對應)

事件列:從手指接觸屏幕至手指離開屏幕威彰,這個過程產(chǎn)生的一系列事件 任何事件列都是以DOWN事件開始出牧,UP事件結束,中間有無數(shù)的MOVE事件

##事件列

????即當一個MotionEvent 產(chǎn)生后歇盼,系統(tǒng)需要把這個事件傳遞給一個具體的 View 去處理,

##1.2 事件分發(fā)的本質(zhì)

????答:將點擊事件(MotionEvent)向某個View進行傳遞并最終得到處理

????即當一個點擊事件發(fā)生后舔痕,系統(tǒng)需要將這個事件傳遞給一個具體的

????View去處理。這個事件傳遞的過程就是分發(fā)過程豹缀。

##1.3 事件在哪些對象之間進行傳遞伯复?

答:Activity、ViewGroup邢笙、View

一個點擊事件產(chǎn)生后啸如,傳遞順序是:

Activity(Window) -> ViewGroup -> View

Android的UI界面是由Activity、ViewGroup氮惯、View及其派生類組合而成的

UI界面

View是所有UI組件的基類

一般Button叮雳、ImageView、TextView等控件都是繼承父類View

ViewGroup是容納UI組件的容器妇汗,即一組View的集合(包含很多子View和子VewGroup)帘不,

其本身也是從View派生的,即ViewGroup是View的子類

是Android所有布局的父類或間接父類:項目用到的布局(LinearLayout杨箭、RelativeLayout等)寞焙,都繼承自ViewGroup,即屬于ViewGroup子類互婿。

與普通View的區(qū)別:ViewGroup實際上也是一個View棺弊,只不過比起View,它多了可以包含子View和定義布局參數(shù)的功能擒悬。

##1.4 事件分發(fā)過程由哪些方法協(xié)作完成?

????答:dispatchTouchEvent() 稻艰、onInterceptTouchEvent()和onTouchEvent()

##Android事件分發(fā)順序:

????Activity(Window) -> ViewGroup -> View

##事件分發(fā)機制詳細流程

????其中:

????super:調(diào)用父類方法

????true:消費事件懂牧,即事件不繼續(xù)往下傳遞

????false:不消費事件,事件也不繼續(xù)往下傳遞 / 交由給父控件onTouchEvent()處理

????接下來尊勿,我將詳細介紹這3個方法及相關流程僧凤。

##dispatchTouchEvent()分發(fā)點擊事件

##onInterceptTouchEvent()分發(fā)攔截事件

##onTouchEvent()事件處理消費

當點擊按鈕的那一刻,會出現(xiàn)(此時是走的默認super方法)

????/MainActivity: dispatchTouchEvent: 0

?????/MyLinerlayout: dispatchTouchEvent: 0

?????/MyLinerlayout: onInterceptTouchEvent: 0

?????/MyButton: dispatchTouchEvent: 0

?????/MyButton: onTouchEvent: 0

??????MyLinerlayout:onTouchEvent 0

??????MainActivity:onTouchEvent 0

?????/ MainActivity: dispatchTouchEvent: 1

?????/MyLinerlayout: dispatchTouchEvent: 1

?????/MyLinerlayout: onInterceptTouchEvent: 1

?????/MyButton: dispatchTouchEvent: 1

?????/MyButton: onTouchEvent: 1

??????MyLinerlayout:1

??????MainActivity:1

也就是說元扔,事件最終在view層的onTouchEvent()處理結束

##MainActivity

????@Override

????public boolean dispatchTouchEvent(MotionEvent ev) {

????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );

????????return true;

????}

??????MainActivity: dispatchTouchEvent: 0

?????/MainActivity: dispatchTouchEvent: 1

代表MainActivity自己把事件消費掉躯保,不繼續(xù)往下分發(fā)

????return false 就代表不處理,事件結束

MainActivity: dispatchTouchEvent: 0

?????/MainActivity: dispatchTouchEvent: 1

##MyLinerlayout

????@Override

????public boolean dispatchTouchEvent(MotionEvent ev) {

????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );

????????return true;

????}

?????/MainActivity: dispatchTouchEvent: 0

?????/MyLinerlayout: dispatchTouchEvent: 0

?????/MainActivity: dispatchTouchEvent: 1

?????/MyLinerlayout: dispatchTouchEvent: 1

????@Override

????public boolean dispatchTouchEvent(MotionEvent ev) {

????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );

????????return false;

????}

?????/MainActivity: dispatchTouchEvent: 0

?????/MyLinerlayout: dispatchTouchEvent: 0

?????/MainActivity: onTouchEvent: 0

?????/MainActivity: dispatchTouchEvent: 1

?????/MainActivity: onTouchEvent: 1

????如果攔截器方法開始攔截返回true澎语,但是viewgroup的onTouchEvent事件默認super()那么事件不會向下分發(fā)途事,會返回給上一級去做處理

@Override

????public boolean onInterceptTouchEvent(MotionEvent ev) {

????????Log.e(TAG, "onInterceptTouchEvent: "+ev.getAction() );

????????return true;

????}

????@Override

????public boolean onTouchEvent(MotionEvent event) {

????????Log.e(TAG, "onTouchEvent: "+event.getAction() );

????????return super.onTouchEvent(event);

????}

????/MainActivity: dispatchTouchEvent: 0

?????/MyLinerlayout: dispatchTouchEvent: 0

?????/MyLinerlayout: onInterceptTouchEvent: 0

?????/MyLinerlayout: onTouchEvent: 0

?????/MainActivity: onTouchEvent: 0

?????/MainActivity: dispatchTouchEvent: 1

?????/MainActivity: onTouchEvent: 1

????如果攔截器方法開始攔截返回true验懊,viewgroup的onTouchEvent同樣返回true()那么viewgroup就會自己把事件處理掉,事件不會繼續(xù)向下分發(fā)

????/MainActivity: dispatchTouchEvent: 0

?????/MyLinerlayout: dispatchTouchEvent: 0

?????/MyLinerlayout: onInterceptTouchEvent: 0

?????/MyLinerlayout: onTouchEvent: 0

?????/MainActivity: dispatchTouchEvent: 1

?????/MyLinerlayout: dispatchTouchEvent: 1

?????/MyLinerlayout: onTouchEvent: 1

????如果攔截器方法返回false和super()尸变,事件都會分發(fā)到下一級view义图,view因為是最后一層,他沒有向下分發(fā)的權利召烂,只有選擇處理或者不處理 碱工,view如果都走默認方法

????@Override

????public boolean dispatchTouchEvent(MotionEvent ev) {

????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );

????????return super.dispatchTouchEvent(ev);

????}

????@Override

????public boolean onTouchEvent(MotionEvent event) {

????????Log.e(TAG, "onTouchEvent: "+event.getAction() );

????????return super.onTouchEvent(event);

????}

????/MainActivity: dispatchTouchEvent: 0

?????/MyLinerlayout: dispatchTouchEvent: 0

?????/MyLinerlayout: onInterceptTouchEvent: 0

?????/MyButton: dispatchTouchEvent: 0

?????/MyButton: onTouchEvent: 0

?????/MainActivity: dispatchTouchEvent: 1

?????/MyLinerlayout: dispatchTouchEvent: 1

?????/MyLinerlayout: onInterceptTouchEvent: 1

?????/MyButton: dispatchTouchEvent: 1

?????/MyButton: onTouchEvent: 1

????如果view的dispatchTouchEvent返回true,代表自己消費奏夫,不在向下傳遞

????@Override

????public boolean dispatchTouchEvent(MotionEvent ev) {

????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );

????????return true;

????}

????/MainActivity: dispatchTouchEvent: 0

/MyLinerlayout: dispatchTouchEvent: 0

/MyLinerlayout: onInterceptTouchEvent: 0

/MyButton: dispatchTouchEvent: 0

/MainActivity: dispatchTouchEvent: 1

/MyLinerlayout: dispatchTouchEvent: 1

/MyLinerlayout: onInterceptTouchEvent: 1

/MyButton: dispatchTouchEvent: 1

????如果view的dispatchTouchEvent返回false怕篷,onTouchEvent(),返回默認super()酗昼,

????表示不處理廊谓,返回上一級viewgroup的onTouchEvent()去做處理,如果返回true仔雷,

????自己消費蹂析,如果返回false或者super()返回Activity的onTouchEvent去處理

????@Override

????public boolean dispatchTouchEvent(MotionEvent ev) {

????????Log.e(TAG, "dispatchTouchEvent: "+ev.getAction() );

????????return false;

????}

????@Override

????public boolean onTouchEvent(MotionEvent event) {

????????Log.e(TAG, "onTouchEvent: "+event.getAction() );

????????return super.onTouchEvent(event);

????}

????/MainActivity: dispatchTouchEvent: 0

/MyLinerlayout: dispatchTouchEvent: 0

/MyLinerlayout: onInterceptTouchEvent: 0

/MyButton: dispatchTouchEvent: 0

/MyLinerlayout: onTouchEvent: 0

/MainActivity: onTouchEvent: 0

/MainActivity: dispatchTouchEvent: 1

/MainActivity: onTouchEvent: 1

如果view的dispatchTouchEvent()返回super(),會走到本類的onTouchEvent()返回true碟婆,自己消費电抚,事件結束。

????/MainActivity: dispatchTouchEvent: 0

/MyLinerlayout: dispatchTouchEvent: 0

/MyLinerlayout: onInterceptTouchEvent: 0

/MyButton: dispatchTouchEvent: 0

/MyButton: onTouchEvent: 0

/MainActivity: dispatchTouchEvent: 1

/MyLinerlayout: dispatchTouchEvent: 1

/MyLinerlayout: onInterceptTouchEvent: 1

/MyButton: dispatchTouchEvent: 1

/MyButton: onTouchEvent: 1

?????如果view的dispatchTouchEvent()返回super()竖共,onTouchEvent()返回false()或者super()蝙叛,會返回到viewgroup的onTouchEvent(),返回false或者super()公给,最終返回Activity的onTouchEvent()去處理如果viewgroup的onTouchEvent返回true()借帘,代表viewgroup自己消費事件,事件結束淌铐。

????/MainActivity: dispatchTouchEvent: 0

/MyLinerlayout: dispatchTouchEvent: 0

?????/MyLinerlayout: onInterceptTouchEvent: 0

?????/MyButton: dispatchTouchEvent: 0

?????/MyButton: onTouchEvent: 0

?????/MyLinerlayout: onTouchEvent: 0

?????/MainActivity: onTouchEvent: 0

?????/MainActivity: dispatchTouchEvent: 1

?????/MainActivity: onTouchEvent: 1

##如果Activity肺然,viewgroup,view的分發(fā)事件默認super()腿准,到view的onTouchEvent()返回false()或者super()時候际起,才會完整的走完真?zhèn)€默認處理事件結構,也就是最后的view的onTouchEvent事件一級級的返回吐葱,最終交給Activity的onTouchEvent事件去處理街望。

????@Override

????public boolean onTouchEvent(MotionEvent event) {

????????Log.e(TAG, "onTouchEvent: "+event.getAction() );

????????return false;//此事件是view的事件

????}

????/MainActivity: dispatchTouchEvent: 0

?????/MyLinerlayout: dispatchTouchEvent: 0

?????/MyLinerlayout: onInterceptTouchEvent: 0

?????/MyButton: dispatchTouchEvent: 0

?????/MyButton: onTouchEvent: 0

?????/MyLinerlayout: onTouchEvent: 0

?????/MainActivity: onTouchEvent: 0

?????/MainActivity: dispatchTouchEvent: 1

?????/MainActivity: onTouchEvent: 1

##總結

##**2.1 Activity???** dispatchTouchEvent(MotionEvent ev) -- 事件分發(fā)

????1.返回true 直接消費掉 ,沒有分發(fā);?

????2.返回false,不消費,但是觸摸事件不做處理;

????3.只有返回super.dispatchTouchEvent(ev)事件才會向子view分發(fā),其實是調(diào)用了PhoneWindow的superDispatchTouchEvent(),進而調(diào)用了DecorView的superDispatchTouchEvent,里面又調(diào)用了super.dispatchTouchEvent(),而DecorView是一個FrameLayout

##onTouchEvent(MotionEvent event) --事件處理

????1.返回false和默認(super.onTouchEvent(event)),不做處理;

????2.返回true,消費事件

2.2 ViewGroup

dispatchTouchEvent(MotionEvent ev) -- 事件分發(fā)

????1.返回true 事件被消費了, 事件未分發(fā)

????2.返回false 事件未分發(fā),事件傳遞到父容器的onTouchEvent()

????3.只有返回super.dispatchTouchEvent(ev),事件才會向下走,里面會調(diào)用onInterceptTouchEvent()

onInterceptTouchEvent(MotionEvent ev) -- 事件攔截

????1.返回true,事件攔截,調(diào)用自己的onTouchEvent()

????2.返回false,事件未攔截,分發(fā)給了子view

????3.super.onInterceptTouchEvent(ev)與返回false效果一樣

onTouchEvent(MotionEvent event)

????1.返回false和super.onTouchEvent(event)事件不消費,事件傳遞給父容器

????2.返回true,事件會被消費

2.3 View

dispatchTouchEvent(MotionEvent event)

????因為它最小,沒有子view,所以這個方法其實沒有進行分發(fā)的能力

????1.返回true,事件被消費,

????2.返回false ,事件傳遞到父容器的onTouchEvent()

????3.只有返回super.dispatchTouchEvent(ev),事件才會向下走,里面會調(diào)用自己 onTouchEvent()

onTouchEvent(MotionEvent event)

????1.返回false()或者super()事件不消費,事件傳遞給父容器

????2.返回true,事件會被消費?

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市弟跑,隨后出現(xiàn)的幾起案子灾前,更是在濱河造成了極大的恐慌,老刑警劉巖孟辑,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哎甲,死亡現(xiàn)場離奇詭異蔫敲,居然都是意外死亡,警方通過查閱死者的電腦和手機烧给,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門燕偶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人础嫡,你說我怎么就攤上這事指么。” “怎么了榴鼎?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵伯诬,是天一觀的道長。 經(jīng)常有香客問我巫财,道長盗似,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任平项,我火速辦了婚禮赫舒,結果婚禮上,老公的妹妹穿的比我還像新娘闽瓢。我一直安慰自己接癌,他們只是感情好,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布扣讼。 她就那樣靜靜地躺著缺猛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪椭符。 梳的紋絲不亂的頭發(fā)上荔燎,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音销钝,去河邊找鬼有咨。 笑死,一個胖子當著我的面吹牛蒸健,可吹牛的內(nèi)容都是我干的摔吏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼纵装,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了据某?” 一聲冷哼從身側響起橡娄,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎癣籽,沒想到半個月后挽唉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滤祖,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年瓶籽,在試婚紗的時候發(fā)現(xiàn)自己被綠了匠童。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡塑顺,死狀恐怖汤求,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情严拒,我是刑警寧澤扬绪,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站裤唠,受9級特大地震影響挤牛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜种蘸,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一墓赴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧航瞭,春花似錦诫硕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至滔吠,卻和暖如春纲菌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疮绷。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工翰舌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人冬骚。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓椅贱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親只冻。 傳聞我的和親對象是個殘疾皇子庇麦,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

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