一、事件传递的整体过程
Activity对view的事件分发过程。
当用户手指触摸到屏幕时,其实就是对MotionEvent事件分发过程 。事件最先传递给了Activity的dispatchTouchEvent进行分发,具体的工件则是由Activity内部的Window完成。window会将事件传递顶层的View也就是decorview ,而decorview一般就是当前最底层的容器(即 setContentView 所设置的view 的父类容器),通过Activity.getWindow().getDecoeView() 获得。
层级关系如下:
Paste_Image.png整个事件分发过程由三个重要的方法共同完成,方法如下:
1、dispatchTouchEvent (MotionEvent ev)
- 对事件进行分发,如果事件能够传递给当前View,那么此方法就一定被调用了。
- 返回结果受当前的View 的onTouchEvent 和下级View 的dispatchTouchEvent 影响。
- 返回结果表示是否消耗当前事件。
2、onIntercaptTouchEvent(MotionEvent ev)
- 只有 ViewGroup有这个方法 ,此方法是内部调用。
- 用来判断是否拦截当前事件,如果当前 View 拦截某个事件之后,那么同一事件序列的其他事件都会交给该View去处理,也就是此方法不会再次被调用。
- 返回结果表示是否拦截当前事件。
3、onTouchEvent(MotionEvennt ev)
- 在dispatchTouchEvent 方法中调用 ,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个序列中,当前View无法再次接收到事件。
二、首先看看源码
Activity如何去处理事件的,Activity#dispatchTouchEvent。
/**
* Called to process touch screen events. You can override this to
* intercept all touch screen events before they are dispatched to the
* window. Be sure to call this implementation for touch screen events
* that should be handled normally.
*
* @param ev The touch screen event.
*
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
第五行代码中通过getWindow()将事件交给Window去处理,在Activity源码getWindow返回一个Window对象,该对象就是Window的子类PhoneWindow对象。
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
在Window#superDispatchTouchEvent方法中将事件交给了mDecor去处理,mDecor是什么?
// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;
看到这里就知道事件就从Window交给DecorView去处理了,从注释可以看出,该View是top-level的view也就是最顶层的View了。我们一般在Activity中setContentView中的View就是其子View。
接下来看DecorView中的superDispatchTouchEvent是怎么处理这个事件的?
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
由于DecorView是继承至FrameLayout的,是ViewGroup类型的,所以在第二行代码可以看出他是调用ViewGroup中的dispatchTouchEvent方法。
以上代码片段中表达的是一个点击事件的整体传递过程: Activity -> Window -> DecorView -> ViewGroup -> View
网友评论