一、事件分发的基本概念
1、MotionEvent View触摸事件通过MotionEvent来表示,主要分为:
- ACTION_DOWN:手指按下
- ACTION_UP:手指抬起
- ACTION_MOVE:手指移动
- ACTION_CANCEL:非正常取消
2、当View的点击事件产生后,首先传递到Activity上,然后一层层传递到ViewGroup中,最终传递到View中。
3、事件分发主要的三个方法:- dispatchTouchEvent:事件分发的方法
- onInterceptTouchEvent:事件拦截的方法。在Activity和View都没有这个方法,如果Activity拦截了那整个屏幕都无法响应事件,View作为事件最后的接收者,要么消耗,要么不处理,也不需要进行事件拦截。
- onTouchEvent:事件处理的方法。返回值为true表示要消耗当前事件。
二、dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); (1) } //window的dispatchTouchEvent方法返回为true时,该方法返回true,否者执行onTouchEvent方法 if (getWindow().superDispatchTouchEvent(ev)) { (2) return true; } return onTouchEvent(ev); }复制代码
(1)
public void onUserInteraction() {}复制代码
此方法为空方法。当此activity在栈顶时,触屏点击按home,back,menu键等都会触发此方法。下拉statubar、旋转屏幕、锁屏不会触发此方法。
(2) getWindow().superDispatchTouchEvent(ev): 调用了抽象类Window的superDispatchTouchEvent抽象方法。具体实现在哪? PhoneWindow是Window的唯一实现类。**PhoneWindow**Overridepublic boolean superDispatchTouchEvent(MotionEvent event) { return mDecor.superDispatchTouchEvent(event);}复制代码
内部调用了DecorView的superDispatchTouchEvent方法,
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker { ......}复制代码
- DecorView类是PhoneWindow类的一个内部类
- DecorView继承自FrameLayout,是所有界面的父类
**DecorView**public boolean superDispatchTouchEvent(MotionEvent event) { return super.dispatchTouchEvent(event);}复制代码
内部调用了ViewGroup的dispatchTouchEvent方法。
总结:getWindow().superDispatchTouchEvent(ev) 是调用了ViewGroup的dispatchTouchEvent方法。
三、onTouchEvent
public boolean onTouchEvent(MotionEvent event) { if (mWindow.shouldCloseOnTouch(this, event)) { finish(); return true; } return false; }复制代码
总结:
- 事件传递路径 Activity -> PhoneWindow -> DecorView -> ViewGroup
- Activity的dispatchTouchEvent方法调用了ViewGroup的dispatchTouchEvent方法,并且如果其返回值为false,才会调用Activity的onTouchEvent方法,此时dispatchTouchEvent返回值受onTouchEvent方法返回值的影响。 (问题:啥时候ViewGroup的dispatchTouchEvent方法返回false,也就是说啥时候onTouchEvent方法会执行)