事件分发机制2-viewgroup的分发流程down

本文详细解析了Android中ViewGroup的事件分发机制,包括onInterceptTouchEvent和dispatchTouchEvent的过程。通过一个ViewPager与ListView的例子,阐述了事件如何在ViewGroup及其子View之间传递。当在ViewPager中重写onInterceptTouchEvent时,会影响ListView的滑动。同时,深入源码分析了dispatchTouchEvent的执行流程,解释了ACTION_DOWN事件的特殊处理以及如何决定事件的最终处理者。
摘要由CSDN通过智能技术生成

笔记之后整理一下

 

Viewpager  放一个listview

如果down事件没有处理 move事件也不处理? -- 针对叶子节点

在viewpager中重写onInterceptTouchEvent方法    对子view进行拦截

return true 的话  

listview将不能滑动

return false的话

listview可以滑动  viewpager将不能滑动

 

对onInterceptTouchEvent()不重写就不会冲突  谷歌进行了处理

 

看下ViewGroup的dispatchTouchEvent分发流程

   public boolean dispatchTouchEvent(MotionEvent ev)    在源码的2578行

 

第一个层级  总经理  viewgroup

第二个层级  总监     viewgroup

第三个层级  清洁工  view   处理事件

Down -- 只有一个

首先在 viewgroup的dispatchtouchevent中

   final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;

                if (!disallowIntercept) {

                    intercepted = onInterceptTouchEvent(ev);

                    ev.setAction(action); // restore action in case it was changed

                } else {

                    intercepted = false;

                }

1.上面代码判断事件是否要拦截

2.不拦截就分发

代码2634   if (!canceled && !intercepted) {  分发  

 if (actionMasked == MotionEvent.ACTION_DOWN|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN) ||actionMasked==MotionEvent.ACTION_HOVER_MOVE) {

分发

down事件才会分发

   if (newTouchTarget == null && childrenCount != 0)  判断有没有子view   buildTouchDispatchChildList对子view进行排序(根据z轴或者书写顺序 前面的优先响应)

 for (int i = childrenCount - 1; i >= 0; i--) { final int childIndex = getAndVerifyPreorderedIndex( childrenCount, i, customOrder);   for循环倒序取出child

 

  if (!child.canReceivePointerEvents()|| !isTransformedTouchPointInView(x, y, child, null))   判断取出的child是否能接收事件 1.visible 2.child.animation  第二个判断是要在能够响应的范围内

假如child可以处理该事件就走  不能处理就for继续走

接下来又调用了 if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign))分发处理事件  将child传入

因为child不为null   执行 dispatchTransformedTouchEvent中的   handled = child.dispatchTouchEvent(transformedEvent);方法 假如child是viewgroup  就会递归调用 

如果 dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign) 返回值为true  就会执行

newTouchTarget = addTouchTarget(child, idBitsToAssign);

 

  private TouchTarget addTouchTarget(@NonNull View child, int pointerIdBits) {

        final TouchTarget target = TouchTarget.obtain(child, pointerIdBits);

        target.next = mFirstTouchTarget;

        mFirstTouchTarget = target;

        return target;

    }

对newTouchTarget进行赋值 

三个条件

 target.next = mFirstTouchTarget = null

newTouchTarget = mFirstTouchTarget =   TouchTarget.obtain(child, pointerIdBits)

alreadyDispatchedToNewTouchTarget = true;

 

接着又往下

 if (mFirstTouchTarget == null) {

                // No touch targets so treat this as an ordinary view.

                handled = dispatchTransformedTouchEvent(ev, canceled, null,

                        TouchTarget.ALL_POINTER_IDS);

            } else {

                // Dispatch to touch targets, excluding the new touch target if we already

                // dispatched to it.  Cancel touch targets if necessary.

                TouchTarget predecessor = null;

                TouchTarget target = mFirstTouchTarget;

                while (target != null) {   因为上面的赋值 while只会执行一次

                    final TouchTarget next = target.next;

                    if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {   //这两个条件判断均为ture

                        handled = true; //会执行  子child处理了 就不处理了

                    } else {

                        final boolean cancelChild = resetCancelNextUpFlag(target.child)

                                || intercepted;

                        if (dispatchTransformedTouchEvent(ev, cancelChild,

                                target.child, target.pointerIdBits)) {

                            handled = true;

                        }

                        if (cancelChild) {

                            if (predecessor == null) {

                                mFirstTouchTarget = next;

                            } else {

                                predecessor.next = next;

                            }

                            target.recycle();

                            target = next;

                            continue;

                        }

                    }

                    predecessor = target;

                    target = next;

                }

            }

 

 

 

 

3.分发或者处理

1.拦截(相当于你是最后一个,事件到底处不处理(全部不处理和拦截一样))

handled = dispatchTransformedTouchEvent(ev, canceled, null,TouchTarget.ALL_POINTER_IDS);(是否处理)

 handled为ture 就代表处理  就不分发了 自己处理了

里面child为null的话就到view的dispatchTouchEvent();看是onTouch还是onClick

3.不拦截 走else

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值