開發中總是遇到事件衝突處理不好的問題,所以想從源碼好好研究下Android中事件分發機制。
借鑑:http://www.cnblogs.com/mengdd/p/3394345.html
Android中提供了ViewGroup、View、Activity三個層次的Touch事件處理。
處理過程是按照Touch事件從上到下傳遞,再按照是否消費的返回值,從下到上返回,即如果View的onTouchEvent返回false,將會向上傳給它的parent的ViewGroup,如果ViewGroup不處理,將會一直向上返回到Activity。
即隧道式向下分發,然後冒泡式向上處理。
首先看Activity中的dispatchTouchEvent方法:
onUserInteraction方法在action_down時會調用,是個空實現,可以重寫這個方法就能知道在Activity運行時,用戶以某種方式與設備互動。
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
處理屏幕觸摸事件,你可以覆寫這個方法來截獲所有的觸摸屏幕事件,是在它們分發到窗口之前截獲。
對於要正常處理的觸摸屏幕事件,要確認調用這個實現。
返回值爲true的時候,表明這個事件被消費
可以看出Activity的事件分發方法最終調了onTouchEvent(ev)方法,代碼如下:
/**
* Called when a touch screen event was not handled by any of the views
* under it. This is most useful to process touch events that happen
* outside of your window bounds, where there is no view to receive it.
*
* @param event The touch screen event being processed.
*
* @return Return true if you have consumed the event, false if you haven't.
* The default implementation always returns false.
*/
public boolean onTouchEvent(MotionEvent event) {
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
return false;
}
如果一個屏幕觸摸事件沒有被這個Activity下的任何View所處理,Activity的onTouchEvent將會調用。
這對於處理window邊界之外的Touch事件非常有用,因爲通常是沒有View會接收到它們的。
返回值爲true表明你已經消費了這個事件,false則表示沒有消費,默認實現中返回false。
可以看出Activity中onTouchEvent返回false,沒有做判斷,也沒有做攔截處理,直接傳給子類。