(1)Activity:控制生命週期 & 處理事件bash
(2)ViewGroup:一組View的集合(含多個子View)ide
(3)View:全部UI組件的基類佈局
(1)dispatchTouchEvent(MotionEvent ev): 用來進行事件分發;ui
(2)onInterceptTouchEvent(MotionEvent ev): 判斷是否攔截事件(只存在於ViewGroup 中);this
(3)onTouchEvent(MotionEvent ev): 處理點擊事件spa
從activity的dispatchEvent(MotionEvent ev)方法開始進行事件的分發,代碼以下:3d
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction(); //空方法,子類可重寫
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}複製代碼
咱們能夠看到activity的dispatchTouchEvent(MotionEvent ev) 方法中調用了getWindow().superDispatchTouchEvent()方法。getWindow()就是window的惟一實現類PhoneWindow。全部咱們能夠接着看PhoneWindow中的superDispatchTouchEvent()方法:code
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}複製代碼
由以上代碼能夠發現PhoneWindow的superDispatchTouchEvent()方法裏面調用的是mDecor.superDispatchTouchEvent()方法。mDecor就是窗口的頂層佈局DecorView。DecorView中的super.DispatchTouchEvent()方法最終調用的是ViewGroup的的dispatchTouchEvent方法。cdn
以上是activity到ViewGroup的時間分發流程,再來看看activity的dispatchTouchEvent()方法,若是getWindow().superDispatchTouchEvent()方法返回true,表示事件被activity中的子控件消費,若是返回false,則會執行activity的onTouchEvent()方法。咱們來看看activity的onTouchEvent()方法:對象
public boolean onTouchEvent(MotionEvent event) {
if (mWindow.shouldCloseOnTouch(this, event)) { //判斷是否有超出邊界,若是超出,直接finish
finish();
return true;
}
return false; //若是沒有超出,表示事件沒有被activity消費,事件結束
}
複製代碼
ViewGroup的事件分發dispatchTouchEvent()方法能夠用一段僞代碼來解釋:
由上圖咱們能夠明白:ViewGroup的dispatchTouchEvent()方法中調用了onInterceptTouchEvent()方法來判斷是否攔截事件,若是攔截,則調用本身的onTouchEvent()方法。若是不攔截,則調用子View的dispatchTouchEvent()方法,將事件分發給子View處理。
View的dispatchTouchEvent()事件分發的僞代碼實現:
由吸上僞代碼能夠判斷,當View設置了TouchListener的時候,會先調用TouchListener的onTouch()方法,若是onTouch()方法返回true,則不會執行View的onTouchEvent()方法,若是返回false纔會執行onTouchEvent()方法。TouchListener、onTouchEvent、ClickListener的優先順序是:TouchListener>onTouchEvent>ClickListener.
上圖介紹了事件分發機制的總體流程:
首先事件分發以後由activity分發到達根佈局ViewGroup,以後會調用ViewGroup的dispatchTouchEvent()方法,dispatchTouchEvent()方法中經過調用ViewGroup自身的interceptTouchEvent()方法來判斷是否對時間進行攔截,若是攔截,則調用自身的onTouchEvent()方法,onTouchEvent()方法判斷是否消費事件,若是消費則事件消費結束,若是不消費,則交給activity的onTouchEvent()方法進行處理;若是不攔截,則事件會交給子View處理,若是子View也是ViewGroup的話,流程跟以上同樣;若是View沒有子View的話,則會調用View的dispatchTouchEvent()方法,View中是沒有攔截方法,全部會直接調用本身的onTouchEvent()方法處理事件,若是事件被消費則事件消費結束,若是View沒有消費事件,則交給它的父ViewonTouchEvent()方法處理,若是父容器都不處理,最終會調用activity的onTouchEvent()方法。