在View的事件分發(fā)最后有個(gè)結(jié)論:在一個(gè)非容器類View的onTouchEvent()里面,如果一個(gè)view的clickable為false,down事件傳遞進(jìn)來(lái)后,什么都不會(huì)執(zhí)行,最后該view的onTouchEvent()會(huì)直接就返回false,而且這一個(gè)Touch事件系列中的后續(xù)move,up事件都不會(huì)傳遞到該view,直到下一個(gè)Touch事件系列到來(lái)(一個(gè)Touch事件系列會(huì)一般經(jīng)歷down---->move----->up)。
這個(gè)結(jié)論其實(shí)在View的事件分發(fā)相關(guān)方法dispatchTouchEvent()和onTouch()以及onTouchEvent()里面并沒(méi)有體現(xiàn),它的體現(xiàn)是在ViewGroup里面的dispatchTouchEvent()。一個(gè)onTouch事件從屏幕上產(chǎn)生,首先會(huì)經(jīng)歷Activity,然后會(huì)經(jīng)歷一系列的ViewGroup,最終才是到上篇分析的View(不是ViewGroup的View),由于ViewGroup的事件分發(fā)內(nèi)容較多,本篇先學(xué)習(xí)Activity的事件分發(fā)源碼
Activity的dispatchTouchEvent()源碼:
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
//down事件會(huì)調(diào)用該方法
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
//上面第二個(gè)if如果走不進(jìn)去調(diào)用onTonchEvent(),并返回其值
return onTouchEvent(ev);
}
onUserInteraction()方法:
public void onUserInteraction() {
}
該方法是空實(shí)現(xiàn),如果我們?cè)贏ctivity里面想對(duì)down事件做些操作,可以重寫這個(gè)方法。接下來(lái)看getWindow().superDispatchTouchEvent(ev)源碼:
//Window類的方法,Window類是個(gè)抽象類
public abstract boolean superDispatchTouchEvent(MotionEvent event);
Window類是個(gè)抽象類,所以直接看調(diào)用者getWindow():
public Window getWindow() {
return mWindow;
}
mWindow是在Activity的attach()里面賦值的:
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback) {
....省略代碼
//給mWinddow賦值
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
.....省略代碼
}
可以看到getWindow().superDispatchTouchEvent(ev)實(shí)際是調(diào)用PhoneWindow的superDispatchTouchEvent(ev)。phoneWindow的superDispatchTouchEvent()源碼如下:
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
最終是調(diào)用DecorView的superDispatchTouchEvent(event),DecorView是整個(gè)View樹的根View,它是繼承FrameLayout的,而FrameLayout又是繼承ViewGroup的,所以事件分發(fā)從就從Activity傳遞到了ViewGroup的dispatchTouchEvent(),ViewGroup的dispatchTouchEvent()如果返回true,Activity的dispatchTouchEvent()就直接返回true.如果返回false就執(zhí)行Activity的onTouchEvent(),并且返回onTouchEvent()的返回值
Activity的onTouchEvent()源碼:
public boolean onTouchEvent(MotionEvent event) {
//Window類的方法
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
return false;
}
shouldCloseOnTouch()方法在Window類里面,PhoneWindow并沒(méi)有重寫,接著看shouldCloseOnTouch():
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
//判斷mCloseOnTouchOutside 標(biāo)記,是否是down事件,是否超出window邊界,以及DecorView是否為空
if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
&& isOutOfBounds(context, event) && peekDecorView() != null) {
return true;
}
return false;
}
該方法主要判斷Touch事件是否在window邊界之外,所以這個(gè)if語(yǔ)句一般是走不進(jìn)來(lái),返回false。最終Activtiy的dispatchTouchEvent()的返回值和onTouchEvent()返回值一樣返回false。
Activity的事件分發(fā)總結(jié):
1,如果是down事件,會(huì)調(diào)用onUserInteraction(),move和up事件不會(huì)
2,事件傳遞到Activity后首先會(huì)去調(diào)用ViewGroup的dispatchTouchEvent(),如果ViewGroup的dispatchTouchEvent()返回true,Activity的dispatchTouchEvent()會(huì)直接返回true,如果ViewGroup的dispatchTouchEvent()返回false,會(huì)再去調(diào)用onTouchEvent(),這時(shí)候Activity的dispatchTouchEvent()返回值和onTouchEvent()一樣