Android點擊事件分發(fā)機制
??? 想要玩轉(zhuǎn)Android自定義控件,除了繪制UI之外页畦,控件的交互也是必不可少的胖替,其中最常見的就是與屏幕的指尖的交互,對于簡單的控件而言豫缨,實現(xiàn)onclick事件就可以了独令,但是對于復(fù)雜交互,還遠遠不夠好芭。今天特意整理Android的事件分發(fā)機制燃箭,以便自己加深理解。
??? 1.dispatchTouchEvent ????????? ————事件分發(fā)方法舍败,分發(fā)Event所調(diào)用
??? 2.onInterceptTouchEvent ? ? ?————事件攔截方法招狸,攔截Event所調(diào)用
??? 3.onTouchEvent ? ? ? ? ? ? ? ? ? ?————事件響應(yīng)方法,處理Event所調(diào)用
兩大類別的view所包含的的方法
?? ? 1.view???????????????? ———dispatchTouchEvent() ??????? onTouchEvent()
????? 2.viewgroup????? ———dispatchTouchEvent()??onInterceptTouchEvent()??? onTouchEvent()
????? 3.activity?????????? ———dispatchTouchEvent() ??????? onTouchEvent()
??????? 為什么activity也會有該觸發(fā)事件邻薯,來看一下源碼
???? activity作為用戶與系統(tǒng)連接的橋梁,肯定是要實現(xiàn)觸摸事件的啊厕诡。和view的實現(xiàn)方法一樣累榜,也是實現(xiàn)了dispatchTouchEvent() ??????? onTouchEvent()這兩個方法。
1.測試布局
activity代碼:
@Override
public boolean onTouchEvent(MotionEvent event){
????? Log.i(TAG,"Activity's onTouchEvent returns super");
????? return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev){
???? Log.i(TAG,"Activity's dispatchTouchEvent returns super");
??? return super.dispatchTouchEvent(ev);
}
viewGroup1代碼:
@Override
public boolean onTouchEvent(MotionEvent event){
?? Log.i(TAG,"ViewGroup1's onTouchEvent returns super");
?? return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev){
??? Log.i(TAG,"ViewGroup1's onInterceptTouchEvent returns super");
??? return? super.onInterceptTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev){
??? Log.i(TAG,"ViewGroup1's dispatchTouchEvent returns super");
?? return super.dispatchTouchEvent(ev);
}
viewGroup2代碼與viewyiGroup一樣灵嫌,無非就是log輸出時將ViewGroup1改為ViewGroup2
View代碼
@Override
public boolean onTouchEvent(MotionEvent event){
?? Log.i(TAG,"View's onTouchEvent returns super");
?? return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev){
?? Log.i(TAG,"View's dispatchTouchEvent returns super");
?? return super.dispatchTouchEvent(ev);
}
這些方法的區(qū)別是什么呢信柿?以及他們的流程是怎樣的的呢冀偶?
??? 我們來打印log看一下輸出的過程:分別在activity中、view中渔嚷,viewgroup中。
1.讓所有的onInterceptTouchEvent稠曼、dispatchTouchEvent及onTouchEvent默認均返回super(父類的實現(xiàn)方法)形病,輕輕點擊MyView然后快速抬起,查看相應(yīng)的Log:
可以仔細看出他的執(zhí)行順序:
然后我們探索dispatchTouchEvent()方法霞幅,令其return false(這里以ViewGroup2的dispatchTouchEvent()方法為例)漠吻,log如下
該流程圖為:
結(jié)論:當dispatchTouchEvent()返回false時,會將事件傳遞給上一級View的onTouchEvent()方法處理司恳。由于Activity已經(jīng)沒有比它更高一級的View途乃,所以如果時Activity的dispatchTouchEvent方法return false的話,事件會直接被消費掉(即終止傳遞)扔傅。
接著讓dispatchTouchEvent()方法return true(這里以ViewGroup2的dispatchTouchEvent()方法為例)耍共,log如下:
可以看到傳遞流程,可以用流程圖表示為:
規(guī)律:如果dispatchTouchEvent()方法返回true時猎塞,事件會被消費掉试读,不再傳遞。
然后我們探索一下onTouchEvent()方法荠耽,令其return false,(這里以最里層的View的onTouchEvent()方法為例)钩骇,log如下:
可以看到傳遞流程,可以用流程圖表示為:
規(guī)律:如果onTouchEvent()方法返回false時铝量,跟默認return super是一樣的倘屹,都會一直向上傳遞到上一級view的onTouchEvent()方法。
事實上慢叨,onTouchEvent()方法super父類的默認實現(xiàn)返回的就是false纽匙。
然后我們讓onTouchEvent()方法return true,(這里以最里層的View的onTouchEvent()方法為例),log如下:
可以看到傳遞流程插爹,可以用流程圖表示為:
規(guī)律:如果onTouchEvent()方法返回true時哄辣,事件會被消費掉,不再傳遞赠尾。跟dispatchTouchEvent()return true的時候類似力穗。
最后,我們來探索onInterceptTouchEvent()方法,令其return false,(這里以最里層的ViewGroup2的onInterceptTouchEvent()方法為例)气嫁,log如下:
規(guī)律:這里就不貼流程圖了当窗,但是可以看到onInterceptTouchEvent()方法return false和return super是一樣的。都是默認將觸摸事件傳給下一級view的dispatchTouchEvent()方法寸宵。
最后崖面,我們讓onInterceptTouchEvent()方法return true,(這里以最里層的ViewGroup2的onInterceptTouchEvent()方法為例)元咙,log如下:
可以看到傳遞流程,可以用流程圖表示為:
規(guī)律:如果onInterceptTouchEvent()方法返回true時巫员,Touch事件會被直接傳遞給ViewGroup自己的onTouchEvent()方法處理庶香。
總結(jié)歸納
1.對于dispatchTouchEvent()方法:
?? return true:消費掉事件,終止傳遞简识。
?? return false: 將事件傳遞給上一級View的onTouchEvent()方法赶掖。如果是Activity的dispatchTouchEvent()方???? 法,則也是消費掉事件七扰,終止傳遞奢赂。
?? return super:如果是Activity,則傳給下一級view(viewGroup)的dispatchTouchEvent;如果是ViewGroup颈走,則傳給自己的onInterceptTouchEvent();如果是View,則傳給自己的onTouchEvent().
2..對于onTouchEvent()方法:
?? return true:消費掉事件膳灶,終止傳遞。
? return false/super:將事件傳遞給上一級view的onTouchEvent()方法立由。
3.對于onInterceptTouchEvent()方法:
?? return true:將事件傳遞給ViewGroup自己的onTouchEvent()方法處理轧钓。
?? return false/super:將事件傳遞給下一級View的dispatchTouchEvent()。
回到之前我們的一個問題拆吆,為什么只有ViewGroup有onInterceptTouchEvent()方法呢聋迎,從上面的整個觸摸事件分發(fā)傳遞機制我們可以發(fā)現(xiàn),ViewGroup本身的dispatchTouchEvent()方法無論返回什么都不能將事件傳遞給自己的onTouchEvent()方法處理枣耀,那就只好設(shè)計了一個這樣子的方法霉晕,作為攔截器,攔截事件交給自己處理了捞奕。只要onInterceptTouchEvent()returntrue就可以實現(xiàn)觸摸事件攔截牺堰。