Activity对触摸事件的分发流程
本文源码基于Android 10.0
首先,用户触摸屏幕之后,会调用Activity的dispatchTouchEvent()方法:
ViewDispatchActivity.java
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e("ViewDispatchActivity", "dispatchTouchEvent");
return 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);
}
以上可知:
Activity.onUserInteraction()
1、如果事件类型为ACTION_DOWN按下操作,则会回调onUserInteraction()方法,表示用户正在与应用进行交互,可以在此实现与用户的交互功能。
ViewDispatchActivity.java
@Override
public void onUserInteraction() {
Log.e("ViewDispatchActivity", "onUserInteraction");
super.onUserInteraction();
}
Activity.java也就是:
public void onUserInteraction() {
}
ViewGroup.superDispatchTouchEvent()
2、如果Window抽象类的实现类PhoneWindow的superDispatchTouchEvent()方法返回true,则当前方法也返回true。
继续看下PhoneWindow,可知调用的是DecorView的superDispatchTouchEvent()方法:
PhoneWindow.java
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
继续看下DecorView,可知调用的是ViewGroup的dispatchTouchEvent()方法:DecorView.java
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
继续看下ViewGroup:ViewGroup.java
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
......
return handled;
}
由此,我们知道了Activity是如何将事件传递给ViewGroup的,并且知道了ViewGroup的dispatchTouchEvent()方法返回结果决定了Activity的dispatchTouchEvent()方法的返回结果。
Activity.onTouchEvent()
3、如果Window抽象类的实现类PhoneWindow的superDispatchTouchEvent()方法返回false,则调用onTouchEvent()方法。ViewDispatchActivity.java
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("ViewDispatchActivity","onTouchEvent");
return super.onTouchEvent(event);
}
也就是:Activity.java
public boolean onTouchEvent(MotionEvent event) {
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
return false;
}
以上可知,如果Window的shouldCloseOnTouch()方法返回true,则结束当前Activity,并且返回true;否则返回false。
继续看下Window的shouldCloseOnTouch()方法:Window.java
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
final boolean isOutside =
event.getAction() == MotionEvent.ACTION\_UP && isOutOfBounds(context, event)
|| event.getAction() == MotionEvent.ACTION\_OUTSIDE;
if (mCloseOnTouchOutside && peekDecorView() != null && isOutside) {
return true;
}
return false;
}
以上可知,如果触摸事件在边界外,将会结束当前Activity,并且返回true,否则返回false。