Android 事件分发机制源码分析

if(MotionEvent.ACTION_DOWN || mFirstTouchTarget != null){
     //初次的down事件到来的时候,只有父view具有决定事件是否拦截的权利。因为此时的disallowIntercept初始值是false,原因是down事件之前会重置这个标志位
     final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
     //第一个down进来下面这个if条件是成立的,因此父view的onInterceptTouchEvent方法就决定了是否拦截
     if(!disallowIntercept){
         intercepted = onInterceptTouchEvent(ev)
     }else{
         //这个条件是子view要求父view不要拦截,其实就是后续的move和up事件不要拦截,因为能进到这个地方不可能是down事件并且mFirstTouchTarget != null
         intercepted = false;
     }
}else{
    //进到这个地方说明事件是move或者up并且mFirstTouchTarget == null。
    //move或者up能进到这个地方说明mFirstTouchTarget == null,那么就意味着要么down被父view消费了(down事件被父view拦截了或者子view不处理down事件又把down事件交给父view处理)
    //要么就是在move或者up的事件子view要求父view进行拦截并且父view拦截了,这样也会导致mFirstTouchTarget == null成立。这样的话子view就再也拿不到事件了
    intercepted = true
}
//新的事件会重置这两个值
TouchTarget newTouchTarget = null;
boolean alreadyDispatchedToNewTouchTarget = false;
//只有不拦截才会命中
if(!canceled && !intercepted){
     //只有down事件才会进行分发
     if (actionMasked == MotionEvent.ACTION_DOWN){
          for(){
             //利用循环遍历按住的子view
             if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
                  //如果找到了处理down事件的子view 就会在addTouchTarget方法里面把 mFirstTouchTarget的值设置成非空
                  newTouchTarget = addTouchTarget(child, idBitsToAssign);
                  //把已经消费的标记为设置成true
                  alreadyDispatchedToNewTouchTarget = true;
                  break;
             }
          }
     }
}
//上面已经解释过mFirstTouchTarget==null的原因了,1、down事件被父view消费掉了 2、子view的move事件交给了父view拦截并且拦截了
if(mFirstTouchTarget == null){
    //自己处理事件
    handled = dispatchTransformedTouchEvent(ev, canceled, null, TouchTarget.ALL_POINTER_IDS);
}else {
    //子view处理事件
    TouchTarget target = mFirstTouchTarget;
    while(target != null){
         if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
             //如果当前事件是down并且down事件被子view处理了这个就会成立
             handled = true;
         }else{
            //事件来的时候会重置alreadyDispatchedToNewTouchTarget = false  能进到这里说明1、down事件被子view处理并且此时的事件不是down事件。
            //如果move或者up事件被拦截了cancelChild则是true否则false
            final boolean cancelChild = resetCancelNextUpFlag(target.child)|| intercepted;
            //交给自己或者子view去处理
            if (dispatchTransformedTouchEvent(ev, cancelChild, target.child, target.pointerIdBits)) {
                     handled = true;
             }
            //如果是自己处理也就是move事件被父view拦截了
            if (cancelChild) {
                //mFirstTouchTarget设置成next 单指为null
                mFirstTouchTarget = next
             }
         }
          target = next;
      }
    }
}

 

posted @ 2022-04-19 16:15  lianzhen  阅读(48)  评论(0编辑  收藏  举报