ViewGroup事件分发

来源:互联网 发布:linux删除多个文件命令 编辑:程序博客网 时间:2024/05/18 19:19

ViewGroup继承自View从写了父类的dispatchTouchEvent而且多了一个onInterceptTouchEvent方法此方法代表是否拦截此事件的分发

 // Check for interception.            final boolean intercepted;            if (actionMasked == MotionEvent.ACTION_DOWN                    || mFirstTouchTarget != null) {                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;                }            } else {                // There are no touch targets and this action is not an initial down                // so this view group continues to intercept touches.                intercepted = true;            }

当我们按下的时候回来到这里,首先会执行onInterceptTouchEvent判断是否拦截,而disallowIntercept代表不允许拦截默认为false我们也可以通过方法设置disallowIntercept的值来达到拦截目的,onInterceptTouchEvent默认返回false,我们可以通过重写这个方法达到拦截目的。

if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {                                // Child wants to receive touch within its bounds.                                mLastTouchDownTime = ev.getDownTime();                                if (preorderedList != null) {                                    // childIndex points into presorted list, find original index                                    for (int j = 0; j < childrenCount; j++) {                                        if (children[childIndex] == mChildren[j]) {                                            mLastTouchDownIndex = j;                                            break;                                        }                                    }                                } else {                                    mLastTouchDownIndex = childIndex;                                }                                mLastTouchDownX = ev.getX();                                mLastTouchDownY = ev.getY();                                newTouchTarget = addTouchTarget(child, idBitsToAssign);                                alreadyDispatchedToNewTouchTarget = true;                                break;                            }
我们直接掉到上面那段代码,此段代码也在dispatchTouchEvent方法中,我们主要关心的是dispatchTransformedTouchEvent方法而在此方法中发现了下面两行代码

if (child == null) {                handled = super.dispatchTouchEvent(event);            } else {                handled = child.dispatchTouchEvent(event);            }
当我们child为空时,也就是把我们上网viewgroup当成view处理,调用suoer.dispatchTouchEvent当child不为空时也就调用子类的dispatchTouchEvent,可以从源码看出disTransformedTouchEvent的调用在一个for循环中,因为viewgroup并不一定一个孩子当dispatchtransformTouchevent返回为true时,会调用newTouchTarget=addTouchTarget(...)

private TouchTarget addTouchTarget(@NonNull View child, int pointerIdBits) {        final TouchTarget target = TouchTarget.obtain(child, pointerIdBits);        target.next = mFirstTouchTarget;        mFirstTouchTarget = target;        return target;    }
在addTouchTarget方法中,会给mFirstTouchTarget赋值,也就是child赋值给它。而当我们的move或up方法进来时当mFirstTouchTarget不为空时,会判断完是否拦截然后直接走下面的代码,而当mfirstTouchTargrt为空时直接走下面的代码


 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) {                    final TouchTarget next = target.next;                    if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {                        handled = true;                    } else {                        final boolean cancelChild = resetCancelNextUpFlag(target.child)                                || intercepted;                        if (dispatchTransformedTouchEvent(ev, cancelChild,                                target.child, target.pointerIdBits)) {                            handled = true;                        }

而当执行up时mFirstTouchTarget清空resetTouchState()--->clearTouchTargets()然年就被清空了

由上总结,当我们拦截down事件时,那么mFirstTouchTarget就为空了,子view就一直不会响应触摸事件,而要想给mFirstTouchTarget赋值就必须在Down中并且子view 的dispatchtouchevent返回true


在子类中重写dispatchTouchEvent中设置getParent().requestDisallowInterceptTouchEvent(boolean disallowIntercept)阻止父类拦截触摸事件intercept=false,这句话要在super.dispatchTouchEvent()之前

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 中百购物卡过期怎么办 得仕卡过期了怎么办 超市购物卡丢了怎么办 中石化油卡丢失怎么办 etc同车换车牌了怎么办 石油加油卡丢了怎么办 石化加油卡丢了怎么办 怎么办中石化的加油卡 中石油油卡丢失怎么办 公司加油卡丢了怎么办 yy频道被回收了怎么办 油卡里的圈存怎么办 农商银行圈存怎么办 社保卡号忘记了怎么办 陕西壳牌加油卡怎么办 联通用超了流量怎么办 联通3g上不了网怎么办 车玻璃水冻住了怎么办 车里玻璃水冻了怎么办 做现货亏了60万怎么办 宿舍太吵晚上睡不着觉怎么办 脚扎了钉子肿了怎么办 龙血树叶子下垂怎么办 龙血树叶子卷曲怎么办 3岁宝宝长期便秘怎么办 4岁小儿便秘严重怎么办 3岁宝宝便秘严重怎么办 3岁宝宝一直便秘怎么办 11个月宝宝便秘怎么办 2个月的宝宝便秘怎么办 宝宝便秘拉不下来怎么办 5一6岁儿童便秘怎么办 3个月宝宝便秘怎么办 8个月宝宝便秘怎么办 孕5个月咳嗽厉害怎么办 孕8个月咳嗽厉害怎么办 拆石膏后关节僵硬怎么办 宝宝的小腿不直怎么办 鸡咳嗽有痰呼噜怎么办 风热感冒怎么办小窍门 吃完虾喝了牛奶怎么办