美文网首页Android开发实用初见
android中的事件传递机制(1)

android中的事件传递机制(1)

作者: 感召的鳞 | 来源:发表于2019-07-28 21:25 被阅读0次

    将分为三部分博客来记录android事件传递机制
    1.首先我先分析一下android中的控件的结构,
    activity作为一个活动中包含一个window窗口,window下可以放多个ViewGroup,viewGroup中可以放多个view
    2.但是我们通过源码可以看出ViewGroup也是继承View的

    public abstract class ViewGroup extends View implements ViewParent, ViewManager {
    

    3.那我就从view开始看起,通过看源码可以发现view中包含两个处理时间的方法,
    dispatchTouchEvent(MotionEvent event)onTouchEvent(MotionEvent event)
    4.我们知道事件传递机制都是先调用dispatchTouchEvent()方法,所有我们看一下源码

       public boolean dispatchTouchEvent(MotionEvent event) {
            if (event.isTargetAccessibilityFocus()) {
                if (!isAccessibilityFocusedViewOrHost()) {
                    return false;
                }
                event.setTargetAccessibilityFocus(false);
            }
    
            boolean result = false;
    
            if (mInputEventConsistencyVerifier != null) {
                mInputEventConsistencyVerifier.onTouchEvent(event, 0);
            }
    
            final int actionMasked = event.getActionMasked();
            if (actionMasked == MotionEvent.ACTION_DOWN) {
                stopNestedScroll();
            }
    
            if (onFilterTouchEventForSecurity(event)) {
                ListenerInfo li = mListenerInfo;
                if (li != null && li.mOnTouchListener != null
                        && (mViewFlags & ENABLED_MASK) == ENABLED
                        && li.mOnTouchListener.onTouch(this, event)) {
                    result = true;
                }
    
                if (!result && onTouchEvent(event)) {
                    result = true;
                }
            }
    
            if (!result && mInputEventConsistencyVerifier != null) {
                mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
            }
            if (actionMasked == MotionEvent.ACTION_UP ||
                    actionMasked == MotionEvent.ACTION_CANCEL ||
                    (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
                stopNestedScroll();
            }
    
            return result;
        }
    

    前几行是关于判读view是否有焦点的代码我们不用看,主要看其中这段代码

     if (li != null && li.mOnTouchListener != null
                        && (mViewFlags & ENABLED_MASK) == ENABLED
                        && li.mOnTouchListener.onTouch(this, event)) {
                    result = true;
                }
    
                if (!result && onTouchEvent(event)) {
                    result = true;
                }
    

    从这段代码中可以看的出来view是先判读用户是否绑定了OnTouchListener,如果绑定了则调用用户定义的onTouch方法,并且把返回值作为最终结果返回。如果没有定义就调用view中的onTouchEvent方法并返回结果。(在onTouch方法中会调用点击事件处理)
    5.看过view的代码你应该知道了view中dispatchTouchEvent()onTouchEvent()的关系了吧,是前者调用了后者。
    6.接下来我们看一下ViewGroup中的代码,这个要比view要复杂一些,通过看源码我们可以看出来ViewGroup继承View并且重写了dispatchTouchEvent();和增加了OnInterceptTouchEvent();
    7.还是首先我们看一下dispatchTouchEvent()中的代码
    由于该方法的代码过长我就不粘贴了,大家可以看自己的android源码,在第1929行就是该方法,这个方法先是在1960行调用了onInterceptTouchEvent方法,并记录返回值intercepted ,如果intercepted==flase那么将调用ViewGroup中的所有子View的dispatchTouchEvent()。一但有某一个view的方法返回true则ViewGroup的dispatchTouch()返回true。
    8.从这一点我们就能知道了onInterceptTouchEvent是怎么进行屏蔽的了,onInterceptTouchEvent返回为true时则不会调用子view的dispatchTouch,只调用viewGroup的super.onTouchEvent()。
    9.那么什么时候viewGroup的子view的dispatchTouch()会返回true?刚才我们在看view的代码的时候知道,当view中的onTouchEvent返回true时分发函数也会返回true。
    10.从这些代码中我们就能理解了,时间是如何向下传递的了。那么如果没有子view呢?在2372行代码中我们能知道,如果没有子view则ViewGroup调用super.dispatchTouch()

    注:viewGroup中的onInterceptTouchEvent默认返回的是false,也就是默认是都要给子view进行事件传递的,但是有些继承了viewGroup并且重写了该方法的就要具体问题具体分析了。

    下一期我讲述事件传递到最低端后是否会回传给上层控件

    相关文章

      网友评论

        本文标题:android中的事件传递机制(1)

        本文链接:https://www.haomeiwen.com/subject/aupqrctx.html