在看事件分发之前,先看一下View、ViewGroup、Activity的对Touch事件的处理。
一、View对Touch事件的处理
public boolean dispatchTouchEvent(MotionEvent event) {
...
boolean result = false;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {//平常常用的onTouch监听事件
result = true;
}
//这里调用了自身的onTouchEvent(event)
if (!result && onTouchEvent(event)) {
result = true;
}
return result;
}
一句话:View 的dispatchTouchEvent()中调用了onTouchEvent(event)。
看下View的onTouchEvent()是如何处理的:
public boolean onTouchEvent(MotionEvent event) {
...
if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
switch (action) {
case MotionEvent.ACTION_UP:
performClick();//点击事件
break;
}
}
}
二、ViewGroup对Touch事件的处理
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
.....
boolean handled = false;
if (onFilterTouchEventForSecurity(ev)) {
...
// Check for interception.
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);//是否拦截事件
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
....
// Dispatch to touch targets.
if (mFirstTouchTarget == null) {//没有child View
// No touch targets so treat this as an ordinary view.
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
// Dispatch to touch targets, excluding the new touch target if we already
// dispatched to it. Cancel touch targets if necessary.
TouchTarget predecessor = null;
TouchTarget target = mFirstTouchTarget;
while (target != null) {
final TouchTarget next = target.next;
if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
handled = true;
} else {
final boolean cancelChild = resetCancelNextUpFlag(target.child)
|| intercepted;
// 有child View ,事件分发到child View
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
....
}
predecessor = target;
target = next;
}
}
...
}
...
return handled;
}
看一下dispatchTransformedTouchEvent()方法
boolean dispatchTransformedTouchEvent{
.....
if (cancel || oldAction == MotionEvent.ACTION_CANCEL) {
event.setAction(MotionEvent.ACTION_CANCEL);
if (child == null) {//没有child View
handled = super.dispatchTouchEvent(event);
} else {// 有childView 时调用了child View的dispatchTouchEvent(event)
handled = child.dispatchTouchEvent(event);
}
event.setAction(oldAction);
return handled;
}
}
onInterceptTouchEvent()方法默认返回false
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
总结:ViewGroup 继承 View,先调用onInterceptTouchEvent(ev)判断是否拦截事件(默认返回false),如果不拦截,有child view就调用child view的dispatchTouchEvent(),没有就调用父类即View.dispatchTouchEvent(event)。
三、Activity对Touch事件的处理
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
//将触摸事件传递更深地View视图层。
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
调用getWindow().superDispatchTouchEvent(ev),将触摸事件传递更深地View视图层。
从这里可以看出来,Activity的root view 消费掉了Touch事件,Activity的onTouchEvent()就不会被执行。
public boolean onTouchEvent(MotionEvent event) {
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
return false;
}
getWindow()返回的是PhoneWindow 对象。PhoneWindow继承Window
看一下PhoneWindow的superDispatchTouchEvent()方法。
// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
boolean handled = mDecor.superDispatchTouchEvent(event);
}
return handled;
}
DecorView 继承了 FrameLayout,也就是说DecorView就是个ViewGroup。
一句话:Activity的onTouchEvent()是否执行,就看root view的Touch事件是否被消费。
以上记录都是学习记录,有什么错误的地方,希望指正!!ViewGroup的事件分发理解的有些模糊。