首先先判断当前事件是否是Down事件,如果是就调用onUserInteraction方法,如果不是就不会调用,所以Up,Move方法不会调用该方法。
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
Activity的attach源码:
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, ....){
.......
mWindow = new PhoneWindow(this, window, activityConfigCallback);
......
}
public Window getWindow() {
return mWindow;
}
从这里看出getWindow
返回的是一个PhoneWindow
对象,
public class PhoneWindow extends Window implements MenuBuilder.Callback
并且PhoneWindow
对象继承自Window
,由于PhoneWindow
类实现了Window
的抽象方法superDispatchTouchEvent
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
这里mDecor
为DecorView
对象,通过查看DecorView
类的
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
由于DecorView
继承自FragmentLayout
public class DecorView extends FrameLayout
而FragmentLayout
又继承自viewGroup
public class FrameLayout extends ViewGroup
所以调用的就是viewgroup
的dispatchTouchEvent
方法
综上:
Activity
的getWindow().superDispatchTouchEvent(ev)
就是调用的Viewgroup dispatchTouchEvent
方法
Window
:是一个抽象基类,作用于外观用户界面和行为策略表示一个窗口,它包含一个View tree
和窗口的layout
参数。View tree的root View
可以通过getDecorView
得到。还可以设置Window的Content View
。其实现类是PhoneWindow。Activity,Dialog,Toast
,都包含一个Window,该Window在Activity的attach()
函数中mWindow = new PhoneWindow(this)
创建。DecorView
:该类是PhoneWindow
类的内部类,继承自FrameLayout
,它是所有应用窗口的根View,PhoneWindow
设置DecorView
为应用窗口的根视图。PhoneWindow
:PhoneWindow
对象帮我们创建了一个PhoneWindow
内部类DecorView
(父类为FrameLayout)窗口顶层视图Activity
的dispatchTouchEvent
方法开始onUserInceration
方法FragmentLayout
,也就是ViewGroup将事件分发给子view,接着调用Activity的setContentView
方法加载viewActivity
下的子view拦截事件,就不会调用Activity的onTouchEvent方法
;当viewgroup的dispatchTouchEvent方法返回true就直接返回,也不会调用Activity的onTouchEvent方法;当子view没有处理事件就交给viewgroup处理,如果还没有处理事件,一直向上传递,最后交给Activity来消费该事件public void onUserInteraction() {}
空实现方法,简单解释:
Key,Touch,Trackball
事件分发到当前Activity就会被调用。如果想让Activity在运行的时候,能够得知用户正在与设备交互,就可以override该方法。onUserLeaveHint
是为了帮助Activities
智能的管理状态栏Notification;特别是为了帮助Activities
在恰当的时间取消Notification
,就是管理通知public boolean onTouchEvent(MotionEvent event) {
//如果Activity下的view没有处理该事件,就会交给Activity来消费该事件
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
return false;
}
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
///判断mCloseOnTouchOutside标记及是否为ACTION_DOWN事件,同时判断event的x、y坐标是不是超出Bounds,然后检查FrameLayout的content的id的DecorView是否为空
final boolean isOutside =
event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(context, event)
|| event.getAction() == MotionEvent.ACTION_OUTSIDE;
if (mCloseOnTouchOutside && peekDecorView() != null && isOutside) {
return true;
}
return false;
}