個人博客:haichenyi.com。感謝關(guān)注
預(yù)知識點
- Android的一次點擊事件由三部分組成:
- ACTION_DOWN(按下):只能有一個
- ACTION_UP(抬起):只能有一個
- ACTION_MOVE(移動):一個或者多個
??為什么移動事件能有多個呢砾省?因為你手指按在屏幕上滑動會觸發(fā)多個MOVE事件,而這次點擊事件的結(jié)束鸳劳,是在你手指離開屏幕的那一刻,才結(jié)束也搓。
- Android的事件傳遞是責(zé)任鏈的模式赏廓,一層一層的向下傳遞涵紊,傳遞到最下層之后,沒人認(rèn)領(lǐng)幔摸,就一層一層的往回傳(這就是很多人說的從外到內(nèi)摸柄,再從內(nèi)到外)
Android點擊事件
結(jié)論
?? 簡單的分析成從 Activity——ViewGroup——View,結(jié)論:如下圖
有幾點要注意:
- dispatch分發(fā)方法既忆,不做任何處理驱负,表示向下分發(fā)
- onIntercept攔截方法,不做任何處理患雇,表示不攔截
- onTouchEvent跃脊,不做任何處理,表示不處理事件
- view group比activity和view多一個攔截方法苛吱。activity不需要攔截方法是因為酪术,他要么向下分發(fā),要么自己處理不需要攔截翠储。view也類似绘雁,要么分發(fā),要么回傳援所。
這個圖就是我們不修改默認(rèn)的返回值的情況下咧七,全部都是super的方式一層一層傳遞的結(jié)論。最上層的activity任斋,中間層的viewgroup,最下層的view耻涛。跟著箭頭的方向看:
- activity的分發(fā)事件不做處理废酷,分發(fā)給中間層view group去做分發(fā)
- view group的分發(fā)事件也不做處理,傳遞給自己的攔截方法
- view group的攔截事件不做處理抹缕,傳遞給最下層的view去做分發(fā)
- view的分發(fā)事件不做處理澈蟆,它也沒有下一層了,所以卓研,它就會傳遞給自己的onTouchEvent方法趴俘,去處理事件
- view的onTouchEvent方法,不做任何處理奏赘,那么寥闪,它就會回傳給中間層view group的onTouchEvent方法
- view group的onTouchEvent方法不做處理,就會回傳給最上層activity的onTouchEvent方法
- 如果磨淌,最上層的activity的onTouchEvent方法也不做處理疲憋,那么,系統(tǒng)就會拋棄這次點擊事件梁只,也就是 這次點擊事件沒有任何反應(yīng)缚柳。
以上就是一次點擊事件不做處理的正常流程
上面的結(jié)論是怎么的出來的呢埃脏?就是新建一個view group,新建一個view秋忙,重寫這幾個方法矗积,打印日志讨勤,其他啥也沒動。
想要驗證上面的結(jié)論,自己也可以去寫了試一下百匆,沒有什么難點,就是打印日志非迹,把view寫到activity布局里面惩歉,然后點擊view就行了
埋個點:這里日志打印都在super前面。
那么裁奇,問題來了桐猬,如果:
- 某一層不想要分發(fā)這次事件,怎么辦呢刽肠?(dispatch)
- view group想要攔截這次事件溃肪,怎么辦?(onIntercept)
- 某一層想自己處理音五,不回傳了惫撰,怎么辦?(onTouchEvent)
某一層不想要分發(fā)這次事件躺涝,怎么辦呢厨钻?(dispatch)
??activity層如果想要不分發(fā)這次點擊事件,自己的onTouchEvent直接處理坚嗜。你只有不調(diào)用super方法夯膀,直接寫死返回值,不管是true苍蔬,還是false诱建,都會直接調(diào)用自己的onTouchEvent方法。就像下面這樣:
//activity的dispatchTouchEvent方法
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v("hcy","activity:dispatchTouchEvent:"+ev.getAction());
//只要你調(diào)用了super方法碟绑,不管是返回true還是false俺猿,都會正常的向下傳遞
// super.dispatchTouchEvent(ev);
return true;
return false;
}
運行的結(jié)論我就不貼出來了。最后再總結(jié)一張總圖
??view group不分發(fā)格仲,此時押袍,activity已經(jīng)分發(fā)下來了,view group不想往下分發(fā)了凯肋,就需要回傳回activity的onTouchEvent方法伯病。寫法如下:
//view group的dispatchTouchEvent方法
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v("hcy","viewGroup:dispatchTouchEvent:"+ev.getAction());
//不調(diào)用super方法,返回true,流程就會在這里中斷午笛,分發(fā)方法就直接消費了這次事件
// return super.dispatchTouchEvent(ev);
return false;
}
??view 不想分發(fā)惭蟋,就需要回傳給view group的onTouchEvent方法,然后是否需要回傳給activity的onTouchEvent方法药磺,就需要view group的onTouchEvent方法的返回值去判斷了告组,后面再說。
//view 的dispatchTouchEvent方法
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.v("hcy","view:dispatchTouchEvent:"+event.getAction());
// return super.dispatchTouchEvent(event);
return false;
}
那么癌佩,結(jié)論就如下表格:
return | true | false | super.dispatchTouchEvent(event) |
---|---|---|---|
activity | 中斷 | 中斷 | 分發(fā) |
view group | 中斷 | 不分發(fā) | 分發(fā) |
view | 中斷 | 不分發(fā) | 分發(fā) |
ps:中斷:表示整個流程就中斷了木缝,沒有任何回調(diào)了
不分發(fā):表示正常回調(diào)围辙,符合預(yù)期
符合預(yù)期我碟,需要去思考一下。我們這里是不分發(fā)姚建,就把事件還給上一層矫俺,那么,
- view group掸冤,就是觸發(fā)activity的onTouchEvent方法厘托。
- view,就是觸發(fā)view group的onTouchEvent方法稿湿。
view group想要攔截這次事件铅匹,怎么辦?(onIntercept)
//view group的攔截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("hcy","viewGroup:onInterceptTouchEvent:"+ev.getAction());
// return super.onInterceptTouchEvent(ev);
return true;
}
攔截事件:表示攔截了自己處理
那么饺藤,結(jié)論就如下表格:
return | true | false | super.onInterceptTouchEvent(event) |
---|---|---|---|
view group | 攔截 | 不攔截 | 不攔截 |
這里的攔截包斑,會觸發(fā)自己的onTouchEvent方法。
上面的不分發(fā)涕俗,是觸發(fā)上一層的onTouchEvent方法舰始。
這里的概念都不能死記硬背,需要結(jié)合上下文去理解咽袜。
某一層想自己處理,不回傳了枕稀,怎么辦询刹?(onTouchEvent)
onTouchEvent是從內(nèi)向外回傳,那么萎坷,我們先來看最內(nèi)層view的onTouchEvent凹联,代碼如下
//view的onTouchEvent代碼
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.v("hcy","view:onTouchEvent:"+event.getAction());
// return super.onTouchEvent(event);
return true;
}
true,表示自己處理哆档,不會往上回傳蔽挠。false,super表示不自己處理,需要回傳
view group的onTouchEvent,代碼如下
//view group的onTouchEvent代碼
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.v("hcy","viewGroup:onTouchEvent:"+event.getAction());
// return super.onTouchEvent(event);
return true;
}
view group的結(jié)論與view的相同澳淑。都是:true比原,表示自己處理,不會往上回傳杠巡。false,super表示不自己處理量窘,需要回傳。
??activity沒有上一層氢拥,不需要回傳蚌铜。所以,activity的onTouchEvent嫩海,不需要去考慮
那么冬殃,結(jié)論就如下表格:
return | true | false | super.onTouchEvent(event) |
---|---|---|---|
view | 自己處理 | 不處理 | 不處理 |
view group | 自己處理 | 不處理 | 不處理 |
到這里,事件的傳遞基本上就說完了叁怪。完整的流程圖如下:
更簡單的理解:
true | false | super | |
---|---|---|---|
dispatch | 中斷 | 不分發(fā) | 正常流程 |
Intercept | 攔截 | 不不攔截 | 正常流程 |
onTouchEvent | 處理 | 不處理 | 正常流程 |
dispatch:是否分發(fā)
Intercept:是否攔截
onTouchEvent:是否自己處理
true:真的
false:假的
分發(fā)需要額外單獨記憶审葬。