美文网首页
Android事件分发机制的源码分析(二)-ViewGroup篇

Android事件分发机制的源码分析(二)-ViewGroup篇

作者: 大佬不是大佬 | 来源:发表于2019-07-27 23:39 被阅读0次

    这里接着上一篇:Android事件分发机制的源码分析(一)-Activity篇 - 简书

    ViewGroup 的事件分发

        通过上一篇,我们得知:getWindow().superDispatchTouchEvent(ev) 最后会传到

    VIewGroup的dispatchTouchEvent()。

    小结:

        cancelAndClearTouchTargets(ev):mFirstTouchTarget的值代表上一次的点击事件状态,mFirstTouchTarget=null则什么也不做;如果有,将mFirstTouchTarget的值用 TouchTarget全接收并执行 target.recycler()回收掉,最后重置为 null。

        resetTouchState(); 将 mGroupFlags 标志位进行了一个清除操作。

    接着往下看:

        根据源码注释:intercepted = true时,对事件进行拦截,不分发;默认是false的,也就是不拦截事件,向下继续分发。

        disallowIntercept这里计算是得出 false值,这是因为上面的 cancelAndClearTouchTargets()与resetTouchState()中,mGroupFlags 和FLAG_DISALLOW_INTERCEPT 被初始化了。但是可以通过调用 requestDisallowInterceptTouchEvent()改变 (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0的值。

        接着看 onInterceptTouchEvent()。

        总结:onInterceptTouchEvent()默认false,表示不拦截事件;true代表 ViewGroup要拦截这个事件,那么同一事件的序列将不会在调用此方法。

    补充:

            MotionEvent.ACTION_POINTER_DOWN :屏幕有多个手指按下,触发。

            MotionEvent.ACTION_HOVER_MOVE :鼠标在窗口或者View区域移动,但没有按下。

           canViewReceivePointerEvents():表示能否接收点击事件,如果 view可见或动画执行完毕,就返回 true。

            isTransformedTouchPoinInView():表示触摸产生的区域是否在 View的范围之内。

    然后,我们接着看 dispatchTransformedTouchEvent()里面是什么。

       情况1: child == null,会调用 view的dispatchTouchEvent(event),这方法到底干了什么,第三篇再讲。

        情况2:child!=null,会调用 child.dispatchTouchEvent(transformedEvent)把事件分发下去,最后回收 Motion事件。

      接着,展开 dispatchTransformedTouchEvent();

         addTouchTarget():对 mFirstTouchTarget = 子View,然后把 alreadyDispatchedToNewTouchTarget设置 true,意思是说:子 View消费了事件,mFirstTouchTarget就指向子 View。

        另外:子View的onTouchEventf()为false,即不消费事件;那么 dispatchTransformedTouchEvent()就变为 false,就不会执行 addTouchTarget(),也就是说mFirstTouchTarget = null,这也是为什么 子View为什么不可以继续处理 ACTION_MOVE事件  和ACTION_UP事件。

           小结:这块代码就是对 ACTION_DWON根据不同情况不同处理。

    true:事件被消费,mFirstTouchTarget不为null

    false:事件未被消费,mFirstTouchTarget为null  

        接着往下看

        

            mFirstTouchTarget == null时,dispatchTransformedTouchEvent(ev, canceled, null,TouchTarget.ALL_POINTER_IDS),当第三个值 为null传进去,代表 child为null表示没有子View。child ==null时,handle = super.dispatchTouchEvent(event)也就是当前 viewGroup会执行 onTouch事件。

             mFirstTouchTarget  != null时,然后就会进入if( alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {},在之前的分析,这俩值都会是true。然后继续判断有无子 View消费。有的话 handler就会返回true,如果返回false,后面就是通过指针赋值,把后面的 MOVE和UP事件进行处理。

        最后总结:

            Android事件分发,是 Activity → ViewGroup → View 。ViewGroup可以通过  onInterceptTouchEvent()进行拦截(默认不拦截),拦截了之后 MOVE、UP不会在调用 onInterceptTouchEvent()。因为 ViewGroup拦截后,mFirstTouchTarget 一直为 null(找不到消费的子VIew)

        

        那么,if(actionMasked == MotionEvent.ACTION_DWON || mFirstTouchTarget != null) 就一直是false,不会进入到里面执行 onTenterceptTouchEvent()。而我们的子View 是无法通过 getParent(). requestDisallowInterceptTouchEvent ()方法来拦截我们的ViewGroup的DOWN事件的,因为DOWN事件每次都会对 FLAG_DISALLOW_INTERCEPT  和 mGroupFlags  进行重置,还是会进入到if中 重新计算intercepted得到值依然是flase。但是可以调用getParent(). requestDisallowInterceptTouchEvent () 来禁止或者允许 我们的 ViewGroup 是否拦截我们的 MOVE 和 UP 事件。如果子类中,Touch事件被消费了,那么ViewGroup 就不会对Touch事件再进行处理。

        最后,ViewGroup 的 dispatchTouchEvent() 是分发,而 View的 dispatchTouchEvent()是分发给自己,处理的方法是 OnTouchEvent ()。而ViewGroup是没有重写 onTouchEvent()。

    相关文章

      网友评论

          本文标题:Android事件分发机制的源码分析(二)-ViewGroup篇

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