} else {
return dispatchGenericMotionEvent(event);
}
}
1.经过层层回调会调用到mView.dispatchPointerEvent
2.我们知道ViewRootImpl
中的mView
就是DecorView
现在事件已经传递到了DecorView
,也就是我们界面的根布局
接下来是事件在Activity
,Window
,DecorView
中的传递
2.4 事件在Activity
,Window
,DecorView
中的传递
//DecorView.java
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
//cb其实就是对应的Activity/Dialog
final Window.Callback cb = mWindow.getCallback();
return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
}
//Activity.java
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
//PhoneWindow.java
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
//DecorView.java
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
可以看到事件分发经过了:DecorView
-> Activity
-> PhoneWindow
-> DecorView
看起来是一个很奇怪的事件流转,事件从DecorView
出发,最后又回到了DecorView
,为什么这样做呢?
2.4.1 为什么ViewRootImpl
不直接把事件交给Activity
?
主要是为了解藕
ViewRootImpl
并不知道有Activity
这种东西存在!它只是持有了DecorView
。所以,不能直接把触摸事件送到Activity.dispatchTouchEvent()
2.4.2 交给Acitivity
后,为什么不直接交给DecorView
开始分发事件呢?
因为Activity
不知道有DecorView
!
但是,Activity
持有PhoneWindow
,而PhoneWindow
当然知道自己的窗口里有些什么了,所以能够把事件派发给DecorView
。
在Android
中,Activity
并不知道自己的Window
中有些什么,这样耦合性就很低了,Activity
不需要知道Window
中的具体内容
2.5 小结
经过上述过程,事件终于到了我们熟悉的ViewGroup.dispatchTouchEvent
流程图如下所示:
下面就是我们最常用也是最常见的事件分发部分了
3.1 ViewGroup
是否拦截事件
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final boolean intercepted;
//只有ActionDown或者mFirstTouchTarget为空时才会判断是否拦截
if (actionMasked == MotionEvent.ACTION_DOWN|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
}
}
if (!canceled && !intercepted) {
//事件传递给子view
…
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
…
//如果子View消耗了则给mFirstTouchTarget赋值
newTouchTarget = addTouchTarget(child, idBitsToAssign);
…
}
}
//mFirstTouchTarget不为空时会调用dispatchTransfor