文化袁探索专栏——事件分发机制

文化袁探索专栏——Activity、Window和View三者间关系
文化袁探索专栏——View三大流程#Measure
文化袁探索专栏——View三大流程#Layout
文化袁探索专栏——消息分发机制
文化袁探索专栏——事件分发机制
文化袁探索专栏——Launcher进程启动流程’VS’APP进程启动流程
文化袁探索专栏——Activity启动流程
文化袁探索专栏——自定义View实现细节
文化袁探索专栏——线程池执行原理|线程复用|线程回收
文化袁探索专栏——React Native启动流程

用户点击屏幕,点击事件会在ViewRootImpl.java类中被接收和处理。然后进行事件的传递。通过view.dispatchPointEvent()将该点击事件传递给DecorView【View视图容器】,之后通过cb.dispatchTouchEvent()【cb是Window】将事件回调传递给Activity。接下来的事件传递流程就是

Activity–>>Window(PhoneWindow)–>>DecorView(FrameLayout)–>ViewGroup–>View

随后,事件经由Activity进行分发。当一个点击事件未被Activity下任何一个View/ViewGroup接收/处理时,则调用onTouchEvent处理事件。反之,则点击事件会经View/ViewGroup继续分发。且事件传递到ViewGroup经过代码流程,在Activity中调用getWindow().superDispatchTouchEvent(event),之后在PhoneWindow中调用mDecor.superDispatchTouchEvent(event),然后在DecorView经super.dispatchTouchEvent(event)将事件传递到Viewgroup。

///Activity.java
public boolean dispatchTouchEvent(MotionEvent ev) {
    
    
        ...
    if (getWindow().superDispatchTouchEvent(ev)) {
    
    
        // 事件在Activity中有ViewGroup接受点击事件
        return true;
    }
    // 没有ViewGroup接受点击事件,Activity则调用onTouchEvent处理事件
    return onTouchEvent(ev);
}

当点击事件分发到ViewGroup时,会先通过变量disallowIntercept、onInterceptTouchEvent方法询问是否进行事件的拦截,若拦截ViewGroup则会自己处理该事件。若不拦截,则ViewGroup会遍历所有子View,查看是否有子View接受了该点击事件。若有,则会通过child.dispatchTouchEvent将该事件分发到View;若无,则将该点击事件通过super.dispatchTouchEvent交由Activity。

当事件分发到View时,在事件分发的方法dispatchTouchEvent中。若注册了Touch事件,会先通过onTouch判断是否进行消费,若被消费则不再进行事件的分发。反之,则执行onTouchEvent进行处理。在onTouchEvent进行处理过程中,若click事件注册,则会消费该点击事件。若click事件未注册则交由上层ViewGroup/Activtiy处理。

///View.java
public boolean dispatchTouchEvent(MotionEvent event) {
    
    
       ...
    if (onFilterTouchEventForSecurity(event)) {
    
    
        if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
    
    
            result = true;
        }
        //noinspection SimplifiableIfStatement
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnTouchListener != null
                && (mViewFlags & ENABLED_MASK) == ENABLED
                // 先通过onTouch判断是否进行消费,若被消费则不再进行事件的分发
                && li.mOnTouchListener.onTouch(this, event)) {
    
    
            result = true;
        }

        if (!result && onTouchEvent(event)) {
    
    
        // onTouch若未消费,则执行onTouchEvent进行处理。
            result = true;
        }
    }
 ...
    return result;
}

ViewGroup到View [心得]touch事件的传递和消费,大致通过递归算法和责任链设计模式实现。- 递归算法,View的传递形成一个DOWN事件责任链TouchTarget(对象是mFirstTouchTarget),并定位到最终接收并消费该点击事件(DOWN事件)的目标View。- 责任链设计模式,指明 后续事件的传递方向,及最终的消费目标。从而完成touch事件的传递、消费~

猜你喜欢

转载自blog.csdn.net/u012827205/article/details/123567033
今日推荐