当我们手指触摸屏幕的时候,事件其实是通过
Activity -> ViewGroup -> View的流程到达我们触摸事件的View的。
事件分发三个重要方法:
- 分发、DispatchTouchEvent()
- 拦截、onInterceptTouchEvent()
- 消费、onTouchEvent()
接下来就按照Activity -> ViewGroup -> View 的流程来大致说一下事件分发机制。
Activity:
当我们手指触摸屏幕时,会触发一个Action_Down的事件,当前Activity首先会做出响应,这时会走到 Activity的dispatchTouchEvent() 方法内。在这个方法内部的简单逻辑如下:
调用getWindow.superDispatchTouchEvent(),如果该方法返回true,表示当前事件已经被处理掉。否则就需要调用Activity的onTouchEvent()方法自己处理
为什么会走到ViewGroup的dispatchTouchEvent()?
getWindow()方法返回了一个Window对象,PhoneWindow是Window的唯一实现类,所以相当于调用了PhoneWindow的superDispatchTouchEvent().
在PhoneWindow的方法中调用的是的mDecor.superDispatchTouchEvent(event)。这个mDecor就是DecorView,DecorView是FrameLayout的子类,FrameLayout是ViewGroup的子类,所以本质上调用的是ViewGroup的DispatchTouchEvent().
ViewGroup:的dispatchTouchEvent()
通过onInterceptTouchEvent()方法判断是否拦截,如果拦截则return自己的onTouchEvent()。
子View:的dispatchTouchEvent()
如果不拦截,调用child.dispatchTouchEvent(),这里会调用子view的onTouchEvent方法,如果子view的onTouchEvent方法返回true,则表示事件被处理。
如果未处理,事件会继续向上传递,调用父View的onTouchEvent方法,直到有view处理该事件,如果一直未处理,最终到达Activity的onTouchEvent方法终止。
onTouch 和 onTouchEvent 的区别
**这两个方法都在 View 的 dispatchTouchEvent()**中
public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
满足以上三点,则返回true。
所以onTouch()方法是优先于onTouchEvent()方法执行的,如果onTouch()方法返回true,那么后续操作会被拦截,onTouchEvent方法不会被执行,onClick方法在onTouchEvent中,所以也不会被执行