• 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;
          }
        }
    }
    
  • 相关阅读:
    JAVA中toString方法
    编辑器未包含main类型解决方法
    Ubuntu中设置环境变量详解
    vim中执行shell命令小结
    vim使用手册
    vim命令总结
    如何修改远程桌面连接3389端口
    Linux磁盘与文件系统管理
    文件与文件系统的压缩与打包命令
    Mininet VM设置笔记
  • 原文地址:https://www.cnblogs.com/lianzhen/p/16165846.html
Copyright © 2020-2023  润新知