When logging or debugging, I just know the result but don’t know why. I will briefly analyze the logic that determines the delivery order. The logic of the delivery order of touch events should be in the parent control’s dispatchTouchEvent() In the code> method, different parent controls may have different methods. If the implementation of this method of the parent control changes, the order may change. However, it generally will not change, so we only look at ViewGroup implementation, look at the source code, it is easy to find the part of the code that passes the touch event to the child control. The basic variable naming appears in the child pile. The key logic should be the following lines dispatchTouchEvent()方法中, 不同的父控件这个方法有可能不一样, 如果父控件的这个方法的实现改变了, 有可能会改变这个顺序.不过一般不会改的, 所以我们只看ViewGroup的实现, 看源码, 很容易找到把触摸事件传递给子控件的那部分代码, 基本变量命名出现child那堆就是了, 关键的逻辑应该是下面几行
final int childrenCount = mChildrenCount;
if (newTouchTarget == null && childrenCount != 0) {
// 省略部分代码
final ArrayList<View> 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);
// 省略一堆后续判断
}
}
Here you can clearly see that a variable final View child is defined. This is the child control to which the event will be passed. Of course, some judgments will be made later before the event will be distributed to it, but here I don’t care anymore. #🎜🎜#
#🎜🎜#The logic that determines the instance of this child is final View child = (preorderedList == null) ? children[childIndex] : preorderedList.get(childIndex);, #🎜🎜#There are two key parameters, preorderedList and childIndex. At this point, you can basically determine that the order of distribution of touch events is determined by these two parameters.#🎜 🎜#
#🎜🎜# Next, look at preorderedList, which calls the method buildOrderedChildList(). The code of this method will not be posted. If you do not set elevation or translationZ on the child control , then it will return empty. If it is set, it will return a list sorted according to the Z axis. Generally, it is not set. If you set the value of the Z axis, then The larger the value on the Z axis, the more priority events are distributed.#🎜🎜#
#🎜🎜#Then look at childIndex. Generally, this value is the order defined in the xml file, but we can use the methods getChildDrawingOrder() and setChildrenDrawingOrderEnabled( boolean enabled) to customize the drawing order of child controls. If you set setChildrenDrawingOrderEnabled(true) then isChildrenDrawingOrderEnabled() will return true, causing the customOrder variable to be true when preorderedList is null, and then will be called getChildDrawingOrder() method to get the index of the child control dispatched by the current event.#🎜🎜#
#🎜🎜#To summarize, the area you clicked has two Views, A and B. They are the same size and overlap in position#🎜🎜#
#🎜🎜#If you set elevation or translationZ for A or B, it will be distributed to the View with the larger value on the Z axis first. The default value for the View that is not set is 0. At this time, the index can only be added to xml. The order of #🎜🎜#
#🎜🎜#If you do not set the value of the Z axis, set setChildrenDrawingOrderEnabled(true) and implement the getChildDrawingOrder() method of the parent control, then the order is It is determined by the implementation in this method. For example, when the incoming parameter of this method is 0, the index of A is returned, and when 1 is passed in, the index of B is returned. Even if the index of A is actually larger than B, then The event will also be passed to A#🎜🎜# first
If you do nothing and just use it normally, then the distribution order is the order of the sub-controls in the xml reverse order, that is, the ones added last are distributed first. In fact If the two controls overlap and what you see is the control added later, then the natural click event will be distributed to the control added later
It’s roughly like this, please correct me if I’m wrong.
When logging or debugging, I just know the result but don’t know why. I will briefly analyze the logic that determines the delivery order.
The logic of the delivery order of touch events should be in the parent control’s
dispatchTouchEvent() In the code> method, different parent controls may have different methods. If the implementation of this method of the parent control changes, the order may change. However, it generally will not change, so we only look at
ViewGroup implementation, look at the source code, it is easy to find the part of the code that passes the touch event to the child control. The basic variable naming appears in the child pile. The key logic should be the following lines
dispatchTouchEvent()
方法中, 不同的父控件这个方法有可能不一样, 如果父控件的这个方法的实现改变了, 有可能会改变这个顺序.不过一般不会改的, 所以我们只看ViewGroup
的实现, 看源码, 很容易找到把触摸事件传递给子控件的那部分代码, 基本变量命名出现child那堆就是了, 关键的逻辑应该是下面几行这里可以明确看到定义了一个变量
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轴的值, 设置了
Here you can clearly see that a variablesetChildrenDrawingOrderEnabled(true)
和实现了父控件的getChildDrawingOrder()
rrreeefinal View child
is defined. This is the child control to which the event will be passed. Of course, some judgments will be made later before the event will be distributed to it, but here I don’t care anymore. #🎜🎜# #🎜🎜#The logic that determines the instance of thischild
isfinal View child = (preorderedList == null) ? children[childIndex] : preorderedList.get(childIndex);
, #🎜🎜#There are two key parameters,preorderedList
andchildIndex
. At this point, you can basically determine that the order of distribution of touch events is determined by these two parameters.#🎜 🎜# #🎜🎜# Next, look atpreorderedList
, which calls the methodbuildOrderedChildList()
. The code of this method will not be posted. If you do not set elevation or translationZ on the child control , then it will return empty. If it is set, it will return a list sorted according to the Z axis. Generally, it is not set. If you set the value of the Z axis, then The larger the value on the Z axis, the more priority events are distributed.#🎜🎜# #🎜🎜#Then look atchildIndex
. Generally, this value is the order defined in the xml file, but we can use the methodsgetChildDrawingOrder()
andsetChildrenDrawingOrderEnabled( boolean enabled)
to customize the drawing order of child controls. If you setsetChildrenDrawingOrderEnabled(true)
thenisChildrenDrawingOrderEnabled()
will returntrue
, causing thecustomOrder
variable to betrue
whenpreorderedList
is null, and thenwill be called getChildDrawingOrder()
method to get the index of the child control dispatched by the current event.#🎜🎜# #🎜🎜#To summarize, the area you clicked has two Views, A and B. They are the same size and overlap in position#🎜🎜#setChildrenDrawingOrderEnabled(true)
and implement thegetChildDrawingOrder()
method of the parent control, then the order is It is determined by the implementation in this method. For example, when the incoming parameter of this method is 0, the index of A is returned, and when 1 is passed in, the index of B is returned. Even if the index of A is actually larger than B, then The event will also be passed to A#🎜🎜# firstIf you do nothing and just use it normally, then the distribution order is the order of the sub-controls in the xml reverse order, that is, the ones added last are distributed first. In fact If the two controls overlap and what you see is the control added later, then the natural click event will be distributed to the control added later
It’s roughly like this, please correct me if I’m wrong.
I think it’s random (guess). For this kind of problem, you can log or debug it and you’ll know.
According to your description, the one above gets the touch event first. If the one above does not handle it, it will be passed to the viewgroup below