ViewGroup事件分发

来源:互联网 发布:淘宝装修显示模板过期 编辑:程序博客网 时间:2024/05/18 20:05

viewGroup 事件分发

第一步 对action_down进行处理

cancelAndClearTouchTarget() mFirstTouchTarget=null

第二步 检查是否拦截

  1. 当事件为action_down且 mFirstTouchTarget !=null (找到可以接收touch事件的view)

判断disallowIntercept 标志,如果为false,那就执行onInterceptTouchEvent(), 如果为true,就将intercepted标志设置为false 且不执行onInterceptTouchEvent()。

disallowIntercept这个标志可以通过 requestDisallowTouchEvent() 设置。

如果action_down且 mFirstTouchTarget !=null 不成立,那么intercepted 就为true

  1. onInterceptTouchEvent() 默认返回false

第三步 检查cancel

通过action 和标记检查cancel ,将值赋给 canceled

第四步 事件分发

  • 根据split 变量判断是否 将事件分发给多个子view ,可以通过setMotionEventSplittingEnable()来设置

  • 如果!canceled 和!intercepted 会进入if 获取子view 的个数 倒序遍历子view (android ui的刷新机制是后添加的在上面,我们希望点击的时候在上层的view先响应点击事件)

  • 通过getTouchTarget()查找当前子view是否在mFirstTouchTarget.next链中,如果在就返回这个target,否则返回null,找到了接受这个Touch事件的view 赋值给newTouchTarget , break跳出for循环。

  • 如果没有找到 执行 dispatchTransformedTouchEvent() 该方法 是一个递归调用,如果子view为viewGroup且事件没有被拦截,就递归调用dispatchTouchEvent() ;如果子view 为view 那么就执行onTouchEvent();dispatchTransformedTouchEvent()返回值为true 说明view消费掉此事件。

  • 满足if条件后 会给 newTouchTarget赋值; 同时将alreadyDispatchedToNewTouchTarget赋值为true;跳出外层for循环,

  • 如果不满足if 条件 即子view的onTouchEvent()返回false 不消耗该事件,无法执行addTouchTarget()

也即mFirstTouchTarget为 null,那么子view 无法处理action_move 和action_up事件

  • 如果newTouchTarget==null && mFirstTouchTarget!=null 说明之前for循环没有找到可以接受Touch事件的view, 然后newTouchTarget 指向了最初的mFirstTouchTarget

  • dispatchTransformedTouchEvent ()返回true , 事件被消费,mFirstTouchTarget != null;

    dispatchTransformedTouchEvent() 返回false ,事件未消费,mFirstTouchTarget==null;

  • 如果派发的事件不是action_down 就不会执行以上逻辑,那么mFirstTouchTarget 可能==null或者!=null

0 0