android 事件分发 ViewGroup

来源:互联网 发布:wlan网络是什么 编辑:程序博客网 时间:2024/05/22 13:04
ViewGroup 比View复杂

View相当予单独的  没什么好说的 
但是 ViewGroup里面存在View

那就是正题来了   昨天已经分析了  今天就直接点 直接来到ViewGroup的
来个例子

布局


代码


默认状态 下 测试 点击按钮

结果出来了  发现 button点击失效了  变成 ontouch在父布局了  这说明 onclick事件肯定在ontouch之后的

 
上一节 说了 事件触摸会调用 该控件的dispatchTouchEvent方法 所以这里猜想
 某个控件 会先去找到该控件的父控件 在父控件里面找dispatchTouchEvent这个方法 而过没有 在找这个父控件的父控件的这个方法 一直找下去 最后 找到了ViewGroup 里面

这和前面的是一样的 前面的是一个View控件 中间没有经过ViewGroup 如果中间经过ViewGroup 那就是进入ViewGroup的dispatchTouchEvent 方法

dispatchTouchEvent 这个方法

进去看了看  我的天  好几百行  但是我们只看我们要看的


会进去 这个onInterceptTouchEvent(ev) 方法  因为不太清楚 上面那个条件是什么  看字面意思
   disallowIntercept 这个 是 不允许中断 

 if (!disallowIntercept) {
                    intercepted = onInterceptTouchEvent(ev);  //允许中断 进入这个
                    ev.setAction(action); // restore action in case it was changed
                } else {
                    intercepted = false;
                }

进去这个方法  我一手一抖 

啥情况  这不是intercepted=false 肯定的啦  不管上面条件如何 

刚才实验 我们在onInterceptTouchEvent 这个方法 返回true  就屏蔽了所有的子View的点击事件 我们以这个intercepted 的值为引入点 继续往下看

来到这里  因为 默认是 false     只有为false才会进入这个判断 所以为true的时候进不去 子View的事件都在这个判断里面 我们进去看看


这一段代码 挺长的  

  if (!canceled && !intercepted) {                if (actionMasked == MotionEvent.ACTION_DOWN                        || (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)                        || actionMasked == MotionEvent.ACTION_HOVER_MOVE) {                    final int actionIndex = ev.getActionIndex(); // always 0 for down                    final int idBitsToAssign = split ? 1 << ev.getPointerId(actionIndex)                            : TouchTarget.ALL_POINTER_IDS;                    // Clean up earlier touch targets for this pointer id in case they                    // have become out of sync.                    removePointersFromTouchTargets(idBitsToAssign);                    final int childrenCount = mChildrenCount;                    if (newTouchTarget == null && childrenCount != 0) {                        final float x = ev.getX(actionIndex);                        final float y = ev.getY(actionIndex);                        // Find a child that can receive the event.                        // Scan children from front to back.                        final View[] children = mChildren;                        final boolean customOrder = isChildrenDrawingOrderEnabled();                        for (int i = childrenCount - 1; i >= 0; i--) {                            final int childIndex = customOrder ?                                    getChildDrawingOrder(childrenCount, i) : i;                            final View child = children[childIndex];                            if (!canViewReceivePointerEvents(child)                                    || !isTransformedTouchPointInView(x, y, child, null)) {                                continue;                            }                            newTouchTarget = getTouchTarget(child);                            if (newTouchTarget != null) {                                // Child is already receiving touch within its bounds.                                // Give it the new pointer in addition to the ones it is handling.                                newTouchTarget.pointerIdBits |= idBitsToAssign;                                break;                            }                            resetCancelNextUpFlag(child);                            if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {                                // Child wants to receive touch within its bounds.                                mLastTouchDownTime = ev.getDownTime();                                mLastTouchDownIndex = childIndex;                                mLastTouchDownX = ev.getX();                                mLastTouchDownY = ev.getY();                                newTouchTarget = addTouchTarget(child, idBitsToAssign);                                alreadyDispatchedToNewTouchTarget = true;                                break;                            }                        }                    }


dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)
 这句 我们 再进去 看一下  因为 确实代码不知道是什么  但是我们可以 带着想法去看 
  我们这里熟悉的只有dispatch~~~的方法  看到这个 最像  
其实 网上很多人都研究 过 不过我的是 比较新的源码 网上都是旧的 还是很多不同的 

我们进去这个方法   上面写了  意思就是 当前view 去处理事件   果然 看到 这个方法  dispatchTouchEvent  这里 我们可以看到  如果child不为空  那就是子view自己dispatch~~  如果为空 那就是父布局来执行了  


所以 现在 又回到昨天的 View的分发事件  点击了效果出来了是返回了true 如果返回false 事件不会被消费

然后继续 看 这里返回true   那么 这句话被执行  这句话  我英语巨水  都知道这是 已经被分发到一个新目标 就是 ViewGroup分发给了子View

=


当这个=true的时候 
不会进入上面 那段很长的代码    直接来到这里

这个方法  肯定是没有child啦 因为child是那个条件为false才有机会有  所以这里肯定是被父控件布局调用

所以现在 可以解释我们刚才的返回 true的被父类(ViewGroup的父类是View  相当于现在这个ViewGroup只是一个View了) 给dispatch~~ 了  


就是onInterceptTouchEvent     这个方法返回false 才有机会进入一个判断 去得到子View  然后再分发的时候会给子View去分发  
返回true就没有得到子View  分发的时候 自己实现


说道这里 其实 我们在运用这个知识点的时候  只需要对 父控件的onInterceptTouchEvent   这个方法做处理就行了 

最后来一个 结构图 



画的有点丑   有点简陋  

以前其实分析过  刚好找到那张图了  也一起拿上来吧  



  写这些 其实 没什么意思 很枯燥   下次 就拿实例 来写  


0 0
原创粉丝点击