題目如下:View事件傳遞棍厂;事件是從哪里到達(dá)Activity的棕孙?ViewRootImpl的作用拷恨?有A脖律、B兩個(gè)Button,各自設(shè)置了OnClickListener腕侄,在A上按下小泉,移動(dòng)到B上抬起,會(huì)觸發(fā)OnClickListener么兜挨?為何?UP事件誰(shuí)接收到了?OnClickListener觸發(fā)的條件是哪些眯分?
1.1?View事件傳遞拌汇;事件是從哪里到達(dá)Activity的?
這個(gè)以后專門寫一篇文章單獨(dú)分析事件如何從屏幕點(diǎn)擊最終到達(dá)Activity的弊决。
1.2 基本三大作用:
作為WindowManager和DecorView的紐帶噪舀,橋梁。
完成View的繪制過(guò)程飘诗,包括measure与倡,layout,draw過(guò)程昆稿。
向DecorView分發(fā)收到的用戶發(fā)起的Event事件纺座,比如按鍵、觸屏事件等溉潭。
1.3? 我們先用代碼驗(yàn)證净响,然后再結(jié)合源碼來(lái)分析
按照在A按鈕按下,然后一直移動(dòng) 直到B按鈕位置才抬起來(lái) 結(jié)果是:
剛按下時(shí)候觸發(fā)A按鈕的 ACTION_DOWN喳瓣,然后在A范圍內(nèi)移動(dòng)馋贤,觸發(fā)ACTION_MOVE,當(dāng)不在A范圍內(nèi)移動(dòng)時(shí)畏陕,沒(méi)有事件觸發(fā)配乓,然后又移動(dòng)到A范圍內(nèi),依然ACTION_MOVE惠毁。最后再移動(dòng)到B按鈕上抬起犹芹,觸發(fā)A按鈕的ACTION_UP。過(guò)程中沒(méi)有觸發(fā)B按鈕任何事件鞠绰。
不會(huì)觸發(fā)OnClickListener
1.4 UP事件被A按鈕收到了羽莺。
1.5 源碼來(lái)分析:
首先看不會(huì)觸發(fā)OnClickListener原因。
而Onclick事件是在UP事件中觸發(fā)
可以看到邏輯也比較簡(jiǎn)單:當(dāng)觸發(fā)ACTION_UP事件時(shí)洞豁,也就是手指抬起時(shí)盐固,當(dāng)View處于Pressed狀態(tài)荒给。就會(huì)觸發(fā)performClickInternal()。這里面也會(huì)調(diào)用performClick刁卜。也就是回調(diào)onClick志电。
所以結(jié)論:當(dāng)A按鈕移出View后再B后抬起是不會(huì)觸發(fā)onClick事件的。
UP事件沒(méi)有被B按鈕處理是B都沒(méi)有處理ACTION_DOWN事件(這是一個(gè)事件序列的開(kāi)端)蛔趴。顯然是不會(huì)觸發(fā)UP事件的挑辆。
1.6 OnClickListener觸發(fā)的條件是哪些?
先給出結(jié)論?
設(shè)置了setOnClicklistener
View沒(méi)有重寫OnTouchEvent(默認(rèn)情況下 這個(gè)方法返回值是clickable,也就是說(shuō)View如果是可點(diǎn)擊的孝情,那么就會(huì)消耗事件)
手指沒(méi)有移動(dòng)出View的范圍
有抬起動(dòng)作鱼蝉。
現(xiàn)在主要分析下如果View重寫OnTouchEvent的情況。為什么就不會(huì)觸發(fā)了OnClick事件了箫荡。
當(dāng)我重寫onTouchEvent 無(wú)論之間返回false或者ture時(shí)魁亦,都不會(huì)觸發(fā)了onClick事件
此時(shí)的日志始終沒(méi)有打印。其實(shí)想想也是我們的onClick回調(diào)是在View#onTouchEvent的ACTION_UP那一段代碼觸發(fā)的羔挡。我們點(diǎn)擊按鈕時(shí)候都沒(méi)觸發(fā)View的onTouchEvent方法怎么會(huì)進(jìn)行onClick回調(diào)呢洁奈。
當(dāng)自定義View時(shí)候重寫了onTouchEvent方法后,還想要響應(yīng)onClick回調(diào)時(shí)绞灼,可以在ACTION_UP里面手動(dòng)調(diào)用
return true;
當(dāng)返回return super.onTouchEvent(event);
現(xiàn)象:onClick 會(huì)觸發(fā)兩次
當(dāng)返回return false; 不會(huì)觸發(fā)利术,即使調(diào)用了performClick(); 因?yàn)閞eturn false代表View不處理此事件了。