Android觸屏事件傳遞
一:前言
之前由於做Launcher部分,涉及到許多交互的部分,因為項目過去很長時間了,最近又在做GTS,CTS的測試與修改,好多都不熟悉甚至忘記了,結合別人的文章經驗(我發現有些地方和別人有出入,但自己經測試驗證),加上自己的測試,今天寫下文章來總結一下。
二:關於ViewGroup與其中的view視圖
ViewGroup是一個容器類,一般,布局容器是繼承字它的。容器裡面可以存放視圖,當然也可以嵌套容器,比如Relativelayout,LinearLayout等等。我這裡所說的view視圖是只繼承view的類,沒有繼承容器類(ViewGroup)。因為後面降到的事件傳遞的小差異和這個有關系。繼承自ViewGroup的類裡面有interceptTouchEvent(),而沒有繼承ViewGroup的類沒有這個方法,這個方法是負責攔截touch事件的。
三:事件傳遞
1:一般,針對ViewGroup ,事件傳遞有三個方法。
dispatchTouchEvent(); 負責事件分發,如果返回值為true,表示事件不繼續分發,也不進行消費(執行onTouchEvent(),如果onTouchEvent()返回true表示消費完,false表示沒有消費完),然後一級一級向上執行容器類的dispatchTouchEvent(),並且每一級的返回值為true;如果dispatchTouchEvent()返回值為false,則交給父類分發給interceptTouchEvent();
interceptTouchEvent();負責事件攔截,如果返回false,表示不攔截,touch事件交給下一級的視圖處理,如果攔截,則交給這一級的onTouchEvent()來處理;
onTouchEvent();負責消費事件,如果返回值為true,表示消費了事件,事件消失;如果返回值為false,則向上一級執行onTouchEvent(),如果上一級繼續返回false,則繼續向上,如果每一級都返回false,則進入死循環,導致ANR,android 5.1也會死循環,我測試不會導致ANR(可能公司手機還沒有適配好),為了避免這種情況,可以在Activity的onTouchEvent()返回true;
........... extends Activity{
public boolean dispatchTouchEvent(MotionEvent ev) {
return true;
}
}
2:針對不是容器類的View
dispatchTouchEvent(); 負責事件分發,如果返回值為true,表示事件不繼續分發,也不進行消費(執行onTouchEvent(),如果onTouchEvent()返回true表示消費完,false表示沒有消費完),這裡注意了,一般這個View都存在於一個容器中,但是不執行父容器的dispatchTouchEvent(),而是執行父父容器的dispatchTouchEvent(),然後向上遞歸傳遞,為什麼?個人覺得是:因為沒有繼承ViewGroup的(不是容器類),它沒有子View,他和父容器的dispatchTouchEvent()處理時是調用的同一個,所以雖然有事件分發函數;如果dispatchTouchEvent()返回值為false,則交給父類分發給onTouchEvent()消費;個人感覺最好不要在dispatchTouchEvent()裡面強行返回false,並且在裡面做UI處理。
onTouchEvent();負責消費事件,如果返回值為true,表示消費了事件,事件消失;如果返回值為false,則向上一級執行onTouchEvent(),如果上一級繼續返回false,則繼續向上,如果每一級都返回false,則進入死循環,導致ANR,android 5.1也會死循環,我測試不會導致ANR(可能公司手機還沒有適配好),為了避免這種情況,可以在Activity的onTouchEvent()返回true;
3:關於Activity的dispatchTouchEvent()和onTouchEvent();
一個事件開始於Activity的dispatchTouchEvent()方法,並向DecorVIew(setContentView()裡面的view)下面傳遞的.
待上圖上代碼