基本過程
View事件分發(fā)的原理是責任鏈模式驰贷,事件層層傳遞债沮,直到被消費胧辽。
從Activity->PhoneWindow->DecorView->ViewGroup->View
,在傳遞的過程中判斷是否要攔截事件确垫,不攔截則交給子View處理子View判斷是否設置了OnTouchListener,根據(jù)onTouch的返回值決定是否要執(zhí)行onTouchEvent
最終如果事件被子View消費了則結束本次事件分發(fā)吟宦,如果沒有被消費則從子View的父容器到Activity依次調用super.dispatchTouchEvent(即ViewGroup的父類View的dispatchTouchEvent方法,與第3步過程一樣)
View的dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent event) {
...
boolean result = false; // result 為返回值篮洁,主要作用是告訴調用者事件是否已經(jīng)被消費。
if (onFilterTouchEventForSecurity(event)) {
ListenerInfo li = mListenerInfo;
/**
* 如果設置了OnTouchListener殃姓,并且當前 View 可點擊袁波,就調用監(jiān)聽器的 onTouch 方法,
* 如果 onTouch 方法返回值為 true蜗侈,就設置 result 為 true篷牌。
*/
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
/**
* 如果 result 為 false,則調用自身的 onTouchEvent宛篇。
* 如果 onTouchEvent 返回值為 true,則設置 result 為 true薄湿。
*/
if (!result && onTouchEvent(event)) {
result = true;
}
}
...
return result;
}
onTouchEvent
public boolean onTouchEvent(MotionEvent event) {
...
final int action = event.getAction();
// 檢查各種 clickable
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
(viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
switch (action) {
case MotionEvent.ACTION_UP:
...
removeLongPressCallback(); // 移除長按
...
performClick(); // 檢查單擊
...
break;
case MotionEvent.ACTION_DOWN:
...
checkForLongClick(0); // 檢測長按
...
break;
...
}
return true; // ??表示事件被消費
}
return false;
}
ViewGroup的dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean result = false; // 默認狀態(tài)為沒有消費過
if (!onInterceptTouchEvent(ev)) { // 如果沒有攔截交給子View
result = child.dispatchTouchEvent(ev);
}
if (!result) { // 如果事件沒有被消費,詢問自身onTouchEvent
//通過調用super.dispatchTouchEvent
result = onTouchEvent(ev);
}
return result;
}