android方向触摸事件,Android布局中同级节点的触摸事件传递顺序

打log或者debug只是知道结果却不知道为何, 我简单分析下决定这个传递顺序的逻辑

触摸事件的传递顺序的逻辑应该在父控件的dispatchTouchEvent()方法中, 不同的父控件这个方法有可能不一样, 如果父控件的这个方法的实现改变了, 有可能会改变这个顺序.不过一般不会改的, 所以我们只看ViewGroup的实现, 看源码, 很容易找到把触摸事件传递给子控件的那部分代码, 基本变量命名出现child那堆就是了, 关键的逻辑应该是下面几行

final int childrenCount = mChildrenCount;

if (newTouchTarget == null && childrenCount != 0) {

// 省略部分代码

final ArrayList preorderedList = buildOrderedChildList();

final boolean customOrder = preorderedList == null && isChildrenDrawingOrderEnabled();

final View[] children = mChildren;

for (int i = childrenCount - 1; i >= 0; i--) {

final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;

final View child = (preorderedList == null) ? children[childIndex] : preorderedList.get(childIndex);

// 省略一堆后续判断

}

}

这里可以明确看到定义了一个变量final View child, 这个就是事件将要传递的子控件, 当然后面还要经过一些判断才会把事件分发给它, 不过这里不关心了.

决定这个child的实例的逻辑是final View child = (preorderedList == null) ? children[childIndex] : preorderedList.get(childIndex);,

关键的参数有两个, preorderedList和childIndex, 到这里基本可以确定触摸事件的分发顺序就是这两个参数决定的了.

接着看preorderedList, 是调用了方法buildOrderedChildList(), 这个方法的代码就不贴出来了, 如果你没有对子控件设置elevation或者translationZ, 那么就会返回空, 如果设置了的话那么返回一个根据Z轴排序的列表, 一般情况下都是没有设置的, 如果你设置了Z轴的值, 那么在Z轴的值越大就越优先分发事件.

然后看childIndex, 一般情况下这个值就是xml文件中定义的顺序了, 不过我们可以通过方法getChildDrawingOrder()和setChildrenDrawingOrderEnabled(boolean enabled)来自定义子控件的绘制顺序, 如果你设置setChildrenDrawingOrderEnabled(true)那么isChildrenDrawingOrderEnabled()就会返回true, 导致customOrder变量在preorderedList为null的情况下是true, 接着就会调用getChildDrawingOrder()方法来获取当前事件分发的子控件的index.

总结, 你点击的区域有两个View, A和B, 它们大小相同, 位置重合

如果你对A或B设置了elevation或者translationZ, 那么会先分发给Z轴上值较大的View, 不设置的View默认是0, 此时index只能是xml上添加的顺序

如果你没有设置Z轴的值, 设置了setChildrenDrawingOrderEnabled(true)和实现了父控件的getChildDrawingOrder()方法, 那么顺序就是由这个方法里的实现确定了, 例如在这个方法传入参数是0的时候返回的是A的index, 传入1的时候返回的是B的index, 即使实际上A的index比B大, 那么事件也会先传递给A

如果你什么都没干, 就是正常使用, 那么分发顺序就是子控件在xml中的顺序的倒序, 就是后添加的先分发, 实际上如果两个控件重合了, 你看到的也是后添加的控件, 那么自然点击事件也是先分发给后添加的控件了

大致是这样, 有错欢迎指正.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值