前言:事件是怎么从Activity到ViewGroup的。
问:我们知道,事件产生于用户按下屏幕的一瞬间,事件生成后,经过一系列的过程来到我们的Activity层,那么事件是怎样从Activity传递到根ViewGroup的呢?
答:事件到达Activity时,会调用Activity#dispatchTouchEvent方法,在这个方法,会把事件传递给Window,然后Window把事件传递给DecorView,而DecorView是什么呢?它其实是一个根View,即根布局,我们所设置的布局是它的一个子View。最后再从DecorView传递给我们的根ViewGroup。所以在Activity传递事件给ViwGroup的流程是这样的:
Activity->Window->DecorView->ViewGroup
下面介绍Android 事件的处理机制
1.事件的分发:
如果一个事件传递到了ViewGroup处,首先会判断当前ViewGroup是否要拦截事件,即调用onInterceptTouchEvent()方法;如果返回true,则表示ViewGroup拦截事件,那么ViewGroup就会调用自身的onTouchEvent来处理事件;如果返回false,表示ViewGroup不拦截事件,此时事件会分发到它的子View处,即调用子View的dispatchTouchEvent方法
方法:public boolean dispatchTouchEvent(MotionEvent ev) {}
2.事件的拦截
// 这个方法也是通过返回的布尔值来决定是否拦截对应的事件,根据具体的实现逻辑,返回true表示拦截这个事件,不继续分发给子视图, // 同时交由自身的onTouchEvent方法进行消费, // 返回false或者super.onInterceptTouchEvent表示不对事件进行拦截,需要继续传递给子视图。
public boolean onInterceptTouchEvent(MotionEvent event) {}
3.事件的消费1 onTouchEvent方法
// 该方法返回值为true表示当前视图可以处理对应的事件,事件将不会向上传递给父视图, // 返回值为false表示当前视图不处理这个事件,事件会被传递给父视图的onTouchEvent方法进行处理。 public boolean onTouchEvent(MotionEvent event) {}
4.事件的消费2 onTouchListener的onTouch方法
View中还有一个触摸监听 : onTouchListener的onTouch方法优先级比onTouchEvent高,会先触发。假如onTouch方法返回false会接着触发onTouchEvent,返回true ,onTouchEvent方法不会被调用。
相关源码参考:
//相关源码 // if (li != null && li.mOnTouchListener != null // && (mViewFlags & ENABLED_MASK) == ENABLED // && li.mOnTouchListener.onTouch(this, event)) { // result = true; // } // // if (!result && onTouchEvent(event)) { // result = true; // }