要從源碼理解整個(gè)事件傳遞過程,必須先從事件傳遞的返回值認(rèn)清整個(gè)事件的消費(fèi)過程,對(duì)整個(gè)事件有大致的了解,為何事件被消費(fèi),為何由子類消費(fèi)
需要注意的幾個(gè)點(diǎn)
主要這三個(gè)方法
dispatchTouchEvent() —— true消費(fèi),false不消費(fèi)(即為分發(fā));false表示事件停止往下面的視圖層級(jí)進(jìn)行傳遞,同時(shí)開始往上面的視圖層級(jí)的onTouchEvent傳遞,也稱為回溯。
oninterceptTouchEvent() —— true消費(fèi),false不消費(fèi)(即為不攔截)
onTouchEvent() —— true消費(fèi),false不消費(fèi)()
而事件分發(fā)一般會(huì)經(jīng)過視圖的三個(gè)層級(jí):Activity、ViewGroup、View。下表會(huì)對(duì)視圖不同的三個(gè)層級(jí)擁有的事件分發(fā)的相關(guān)方法進(jìn)行整理:
| 事件分發(fā)相關(guān)方法 | 方法功能 | Activity | ViewGroup | View |
|---|---|---|---|---|
| public boolean dispatchTouchEvent | 事件分發(fā) | + | + | + |
| public boolean onInterceptTouchEvent | 事件攔截 | + | ||
| public boolean onTouchEvent | 事件消費(fèi) | + | + | + |
view因?yàn)闆]有孩子,沒有onInterceptTouchEvent
onTouchEvent中對(duì)點(diǎn)擊事件的具體處理流程大概如下,只要View的CLICKABLE和LONG_CLICKABLE有一個(gè)為true,那么它就會(huì)消耗事件,返回true??偟膩碚f,View的可不可用不影響是否消耗事件,只要clickable或者longClickable有一個(gè)為true,那么它就會(huì)消耗事件。
ViewGroup默認(rèn)不攔截任何事件,因?yàn)閺脑创a中可以看到ViewGroup的onInterceptTouchEvent方法默認(rèn)返回false.
由View中dispatchTouchEvent可知,如果一個(gè)控件是可點(diǎn)擊的,那么點(diǎn)擊該控件時(shí),dispatchTouchEvent的返回值必定是true
public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
- ViewGroup中dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
final float xf = ev.getX();
final float yf = ev.getY();
final float scrolledXFloat = xf + mScrollX;
final float scrolledYFloat = yf + mScrollY;
final Rect frame = mTempRect;
boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (action == MotionEvent.ACTION_DOWN) {
if (mMotionTarget != null) {
mMotionTarget = null;
}
if (disallowIntercept || !onInterceptTouchEvent(ev)) {
ev.setAction(MotionEvent.ACTION_DOWN);
final int scrolledXInt = (int) scrolledXFloat;
final int scrolledYInt = (int) scrolledYFloat;
final View[] children = mChildren;
final int count = mChildrenCount;
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
|| child.getAnimation() != null) {
child.getHitRect(frame);
if (frame.contains(scrolledXInt, scrolledYInt)) {
final float xc = scrolledXFloat - child.mLeft;
final float yc = scrolledYFloat - child.mTop;
ev.setLocation(xc, yc);
child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
if (child.dispatchTouchEvent(ev)) {
mMotionTarget = child;
return true;
}
}
}
}
}
}
boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||
(action == MotionEvent.ACTION_CANCEL);
if (isUpOrCancel) {
mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
}
final View target = mMotionTarget;
if (target == null) {
ev.setLocation(xf, yf);
if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
ev.setAction(MotionEvent.ACTION_CANCEL);
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
}
return super.dispatchTouchEvent(ev);
}
if (!disallowIntercept && onInterceptTouchEvent(ev)) {
final float xc = scrolledXFloat - (float) target.mLeft;
final float yc = scrolledYFloat - (float) target.mTop;
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
ev.setAction(MotionEvent.ACTION_CANCEL);
ev.setLocation(xc, yc);
if (!target.dispatchTouchEvent(ev)) {
}
mMotionTarget = null;
return true;
}
if (isUpOrCancel) {
mMotionTarget = null;
}
final float xc = scrolledXFloat - (float) target.mLeft;
final float yc = scrolledYFloat - (float) target.mTop;
ev.setLocation(xc, yc);
if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
ev.setAction(MotionEvent.ACTION_CANCEL);
target.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
mMotionTarget = null;
}
return target.dispatchTouchEvent(ev);
}
子view的onTouchEvent如果默認(rèn)false不消費(fèi)的話,會(huì)交給上級(jí)的onTouchEvent
viewGroup如果onInterceptTouchEvent不攔截,繼續(xù)交給子view
viewGroup如果dispatchTouchEvent返回true,消費(fèi)掉會(huì)還給上級(jí)的onTouchEvent
如果上面的點(diǎn)你都清楚的話,說明對(duì)事件分發(fā)是有清楚認(rèn)識(shí)的,那么接下來上圖

