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; } } }