preface

There are many articles on the network about the View event distribution mechanism, I have read a lot, most of the first is a variety of conclusions and source analysis, temporarily do not evaluate the analysis and conclusion is correct, only from such a starting point to learn the View event distribution mechanism is inappropriate.

Android View event distribution process is diverse, this article will guide readers without looking at a line of source code, through an example and more than a dozen event distribution flow chart to analyze the View event distribution mechanism. Without further ado, practice is the sole criterion for testing truth, let’s begin to learn.

This article outline

The preparatory work

View event distribution is outside-in, always passing from parent View to child View. Here I’ve written three custom Views to visually analyze the process in a way that’s best understood.

These three views are the OuterViewGroup, InnerViewGroup, and MyView. Inherit from ViewGroup, ViewGroup, View. For OuterViewGroup and InnerViewGroup, you need to rewrite the onMeasure method to measure all the child views, and rewrite the onLayout method to determine the position of the child views relative to itself. The Kotlin code is as follows.

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    measureChildren(widthMeasureSpec, heightMeasureSpec)
}

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
    for (i in 0 until childCount){
        val child = getChildAt(i)
        child.layout(0.0, child.measuredWidth, child.measuredHeight)
    }
}
Copy the code

The code calls measureChildren in onMeasure, placing each child View in the upper left corner of its own onLayout. We then display the three views in the TestActivity layout file with the following XML code.


      
<cn.blogss.core.test.OuterViewGroup
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/green">
    <cn.blogss.core.test.InnerViewGroup
        android:layout_width="@dimen/dp_300"
        android:layout_height="@dimen/dp_400"
        android:background="@color/gray">
        <cn.blogss.core.test.MyView
            android:layout_width="@dimen/dp_200"
            android:layout_height="@dimen/dp_200"
            android:background="@color/burlywood"/>
    </cn.blogss.core.test.InnerViewGroup>
</cn.blogss.core.test.OuterViewGroup>
Copy the code

The final display looks like this.

Some readers may ask, directly use two LinearLayout set a Button is not the same effect, why bother. In fact, the system comes with these controls inside many of the View events have been intercepted (consumption) processing, it is not convenient for us to get a correct result, so the custom View inherit ViewGroup or View to analyze, the final result must be the most accurate, pure, original.

1. Default event distribution process

With the experimental conditions briefly in place, let’s take a look at the View’s default event distribution process. By default, we do not intercept any View events, following the system’s default rules. In this case, override the dispatchTouchEvent and onTouchEvent methods of OuterViewGroup, InnerViewGroup, MyView and TestActivity, and log out their call order, You can get the View event distribution process. The pseudo-code is as follows, omitting the log printing code.

override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
    return super.dispatchTouchEvent(ev)
}

override fun onTouchEvent(event: MotionEvent): Boolean {
    return super.onTouchEvent(event)
}
Copy the code

A slight swipe of the finger on the MyView and then lift produces a complete ACTION_DOWN, ACTIOIN_MOVE, ACTION_UP event, on which the event distribution process described below is based. Note that the dispatchTouchEvent and onTouchEvent methods of a View or ViewGroup return false by default, that is, no event is intercepted. Here is the passing result of the event as the finger slides over MyView.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN
MyView: dispatchTouchEvent: action = ACTION_DOWN
MyView: onTouchEvent: action = ACTION_DOWN
InnerViewGroup: onTouchEvent: action = ACTION_DOWN
OuterViewGroup: onTouchEvent: action = ACTION_DOWN
TestActivity: onTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
TestActivity: onTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
TestActivity: onTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

OuterViewGroup corresponds to ViewGroup1. InnerViewGroup corresponds to ViewGroup2. MyView corresponds to View.

Based on the log results, the default event distribution flow chart can be drawn as follows.

ACTION_DOWN event delivery

ACTION_DOWN is passed from TestActivity’s dispatchTouchEvent to MyView’s dispatchTouchEvent. The onTouchEvent of MyView is then passed outward to the onTouchEvent of TestActivity.

ACTION_MOVE event passing

ACTION_MOVE is generated after the ACTION_DOWN event. Since there is no Activity or View to intercept the ACTION_DOWN event, the ACTION_MOVE stops when it is passed to TestActivity. You can see that the delivery of ACTION_MOVE events is affected by ACTION_DOWN events.

ACTION_UP event transmission

As with ACTION_MOVE events, ACTION_UP stops being passed down to TestActivity due to ACTION_DOWN event interception.

conclusion

According to the above analysis, by default, this is the conclusion.

  1. For ACTION_DOWN events, dispatchTouchEvent is passed from the outermost dispatchTouchEvent to the innermost dispatchTouchEvent, and then from the innermost onTouchEvent to the outermost onTouchEvent.

  2. For ACTION_MOVE and ACTION_UP, only dispatchTouchEvent and onTouchEvent are passed to the Activity.

2. Intercept events at dispatchTouchEvent

2.1 Intercept events in the Activity’s dispatchTouchEvent

Modify the TestActivity code to return true in dispatchTouchEvent to intercept a complete event.

override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
    return true
}
Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
TestActivity: dispatchTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

The flowchart for intercepting events in the Activity’s dispatchTouchEvent is as follows.

ACTION_DOWN event delivery

When the ACTION_DOWN event is passed to TestActivity, it stops passing down.

ACTION_MOVE event passing

As with ACTION_DOWN events, passing to TestActivity stops passing down.

ACTION_UP event transmission

Pass to TestActivity as ACTION_DOWN and stop passing down.

2.2 Intercepting events in the ViewGroup dispatchTouchEvent

Modify the InnerViewGroup code to return true in dispatchTouchEvent to intercept a complete event.

override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
    return true
}
Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
OuterViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: dispatchTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
OuterViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: dispatchTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

The flowchart for intercepting events in ViewGroup2’s dispatchTouchEvent is as follows.

ACTION_DOWN event delivery

Because the dispatchTouchEvent in InnerViewGroup intercepts all events, ACTION_DOWN events can only be passed to InnerViewGroup from TestActivity, and MyView receives no events.

ACTION_MOVE event passing

ACTION_MOVE is passed from TestActivity to InnerViewGroup, and MyView receives no events.

ACTION_UP event transmission

ACTION_UP is passed from TestActivity to InnerViewGroup, and MyView receives no events.

Here’s a question for the reader: what would the flow look like if events were intercepted in ViewGroup1’s dispatchTouchEvent?

2.3 Intercept events in the View’s dispatchTouchEvent

Modify the MyView code to return true in dispatchTouchEvent to intercept a complete event.

override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
    return true
}
Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN
MyView: dispatchTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
OuterViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: dispatchTouchEvent: action = ACTION_MOVE
MyView: dispatchTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
OuterViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: dispatchTouchEvent: action = ACTION_UP
MyView: dispatchTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

The flowchart for intercepting an event in a View’s dispatchTouchEvent is as follows.

ACTION_DOWN event delivery

ACTION_DOWN passes from the outermost layer (TestActivity) to the innermost layer (MyView).

ACTION_MOVE event passing

ACTION_MOVE is passed from the outermost layer (TestActivity) to the innermost layer (MyView).

ACTION_UP event transmission

ACTION_UP passes from the outermost layer (TestActivity) to the innermost layer (MyView).

conclusion

According to the above analysis, the following conclusions can be drawn by intercepting events in dispatchTouchEvent.

  1. inActivity.ViewGroup.ViewThe dispatchTouchEvent intercepts events, all events can only be delivered to the intercepted location, and controls within it will not receive any events.

3. Intercept the event in onTouchEvent

Above, we analyzed the event transmission rule of intercepting events in dispatchTouchEvent and found that all events would be transmitted from the outermost dispatchTouchEvent to the dispatchTouchEvent at the interception and then stopped. So let’s look at the event-passing rules for intercepting events in onTouchEvent.

3.1 Intercepting events in the Activity’s onTouchEvent

Modify the TestActivity code to return true in onTouchEvent to intercept a complete event.

override fun onTouchEvent(event: MotionEvent): Boolean {
    return true
}
Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN
MyView: dispatchTouchEvent: action = ACTION_DOWN
MyView: onTouchEvent: action = ACTION_DOWN
InnerViewGroup: onTouchEvent: action = ACTION_DOWN
OuterViewGroup: onTouchEvent: action = ACTION_DOWN
TestActivity: onTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
TestActivity: onTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
TestActivity: onTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

The flow chart for intercepting events in the Activity’s onTouchEvent is the same as the default event distribution process.

ACTION_DOWN event delivery

ACTION_DOWN events have the same default delivery rules. From TestActivity’s dispatchTouchEvent to MyView’s dispatchTouchEvent, The onTouchEvent of MyView is then passed outward to the onTouchEvent of TestActivity.

ACTION_MOVE event passing

The ACTION_MOVE event stops when passed to TestActivity, just as the default delivery rule does.

ACTION_UP event transmission

The ACTION_UP event stops when passed to TestActivity, as is the default delivery rule.

3.2 Intercepting events in ViewGroup onTouchEvent

Modify the InnerViewGroup code to return true in onTouchEvent to intercept a complete event.

override fun onTouchEvent(event: MotionEvent): Boolean {
    return true
}
Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN
MyView: dispatchTouchEvent: action = ACTION_DOWN
MyView: onTouchEvent: action = ACTION_DOWN
InnerViewGroup: onTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
OuterViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: onTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
OuterViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: onTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

The following is a flowchart for intercepting events in onTouchEvent of ViewGroup2.

ACTION_DOWN event delivery

ACTION_DOWN events are passed from TestActivity’s dispatchTouchEvent to MyView’s dispatchTouchEvent, The onTouchEvent of MyView is then passed out to the onTouchEvent of InnerViewGroup.

ACTION_MOVE event passing

ACTION_MOVE events are passed from TestActivity’s dispatchTouchEvent to InnerViewGroup’s dispatchTouchEvent, And then it stops when it reaches onTouchEvent in InnerViewGroup.

ACTION_UP event transmission

Same as ACTION_MOVE event.

3.3 Intercept events in the View onTouchEvent

Modify the MyView code to return true in onTouchEvent to intercept a complete event.

override fun onTouchEvent(event: MotionEvent): Boolean {
    return true
}
Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN
MyView: dispatchTouchEvent: action = ACTION_DOWN
MyView: onTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
OuterViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: dispatchTouchEvent: action = ACTION_MOVE
MyView: dispatchTouchEvent: action = ACTION_MOVE
MyView: onTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
OuterViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: dispatchTouchEvent: action = ACTION_UP
MyView: dispatchTouchEvent: action = ACTION_UP
MyView: onTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

A flowchart for intercepting an event in a View’s onTouchEvent is shown below.

ACTION_DOWN event delivery

ACTION_DOWN events are passed from the outside in to MyView because the event is intercepted in MyView’s onTouchEvent, so ACTION_DOWN stops being passed out in MyView.

ACTION_MOVE event passing

Same as the ACTION_DOWN event delivery process.

ACTION_UP event transmission

Same as the ACTION_DOWN event delivery process.

conclusion

Now that we have analyzed the event passing rules for intercepting events in dispatchTouchEvent and onTouchEvent, we will conclude by combining the two intercepting methods and looking at the internal relationship between the two intercepting methods.

  1. As you can see, event delivery follows the order from outside-in (dispatchTouchEvent for outer layer to dispatchTouchEvent for inner layer), and then from inside out (onTouchEvent for inner layer to onTouchEvent for outer layer).

  2. It is also easy to understand that if an event is intercepted (consumed) while being delivered from the outside in, then the inside-out process does not occur.

  3. Intercepting (consuming) events in onTouchEvent does not affect the event passing from the outside in to the interceptor.

  4. Intercepting (consuming) events in onTouchEvent only affects the process of event transfer from inside to outside. For ACTION_MOVE, onTouchEvents inside and outside will not be called.

  5. As you can see from the printed logs and flow charts, the flow of ACTION_MOVE and ACTION_UP events is the same under any interception strategy, including the one discussed below.

4. Intercept events in onInterceptTouchEvent

The onInterceptTouchEvent method is useful in situations where sliding conflicts occur. Therefore, it is necessary to investigate the order in which events are intercepted in the onInterceptTouchEvent method of the ViewGroup.

4.1 Intercepting all events in onInterceptTouchEvent

Overriding onInterceptTouchEvent in InnerViewGroup returns true.

override fun onInterceptTouchEvent(ev: MotionEvent?) : Boolean { return true }Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: onTouchEvent: action = ACTION_DOWN
OuterViewGroup: onTouchEvent: action = ACTION_DOWN
TestActivity: onTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
TestActivity: onTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
TestActivity: onTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

The flow chart for intercepting all events in ViewGroup2’s onInterceptTouchEvent is as follows.

ACTION_DOWN event delivery

The ACTION_DOWN event is passed from the outside in to InnerViewGroup and then from the inside out to TestActivity.

ACTION_MOVE event passing

The ACTION_MOVE event is passed only to TestActivity, not to InnerViewGroup.

ACTION_UP event transmission

Same as ACTION_MOVE event.

4.2 Intercepting events in onInterceptTouchEvent and onTouchEvent

Override onInterceptTouchEvent and onTouchEvent in InnerViewGroup, returning true.

override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
    return true
}

override fun onTouchEvent(ev: MotionEvent): Boolean {
    return true
}
Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: onTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
OuterViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: onTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
OuterViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: onTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

The flow chart for intercepting events in onInterceptTouchEvent and onTouchEvent is as follows.

ACTION_DOWN event delivery

The ACTION_DOWN event is passed to InnerViewGroup and stops.

ACTION_MOVE event passing

The ACTION_MOVE event is passed to InnerViewGroup and stops.

ACTION_UP event transmission

The ACTION_UP event is passed to InnerViewGroup and stops.

conclusion

  1. Simply intercepting in onInterceptTouchEvent, ACTION_DOWN stops passing at the intercepting point, and subsequent ACTION_MOVE passes only to the Activity.

  2. If an event is intercepted in both onInterceptTouchEvent and onTouchEvent, subsequent ACTION_MOVE can be passed to the interceptor.

5. Intercepting ACTION_MOVE events (mandatory)

The above analysis basically covers all the interception strategies for events, at which point the reader should have a global understanding of the flow of event delivery. Next, we will study the interception of ACTION_MOVE events. This part is the focus of the full text, and we hope readers can firmly grasp it.

The purpose of studying the View event distribution mechanism is to be able to write a standard custom View, in the face of some custom View with gesture interaction or sliding conflicts, we can solve these problems. Handling ACTION_MOVE events is the focus.

5.1 Intercepting the ACTION_MOVE Event in onInterceptTouchEvent

Note that if you want to intercept ACTION_MOVE events, then ACTION_MOVE must be able to be passed to the interception point. It is absurd to talk about intercepting ACTION_MOVE if ACTION_MOVE can’t even reach the interception. According to the analysis above, return true in MyView onTouchEvent so that ACTION_MOVE can be passed from the outermost layer to the innermost layer. Recall the diagram from section 3.3.

So overriding MyView’s onTouchEvent returns true.

override fun onTouchEvent(ev: MotionEvent): Boolean {
    return true
}
Copy the code

Then override the onInterceptTouchEvent in InnerViewGroup to intercept ACTION_MOVE events. The rest of the events follow the default rule of not intercepting ACTION_MOVE events.

override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
    when(ev.action) {
        MotionEvent.ACTION_MOVE -> {
            return true}}return super.onInterceptTouchEvent(ev) 
}
Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN
MyView: dispatchTouchEvent: action = ACTION_DOWN
MyView: onTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
OuterViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: dispatchTouchEvent: action = ACTION_MOVE
MyView: dispatchTouchEvent: action = ACTION_CANCEL
MyView: onTouchEvent: action = ACTION_CANCEL

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
OuterViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: onTouchEvent: action = ACTION_MOVE
TestActivity: onTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
OuterViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: onTouchEvent: action = ACTION_UP
TestActivity: onTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

The flow chart for intercepting ACTION_MOVE events in onInterceptTouchEvent is as follows.

ACTION_DOWN event delivery

Since we did not intercept any ACTION_DOWN event and only returned true in MyView onTouchEvent, the transfer of ACTION_DOWN event is consistent with the ACTION_DOWN process in section 3.3.

ACTION_MOVE event passing

To make the results clearer, HERE I have triggered the ACTION_MOVE event twice.

The first ACTION_MOVE is passed from TestActivity to InnerViewGroup. Because we intercepted ACTION_MOVE in InnerViewGroup, we definitely couldn’t pass MyView. Instead, ACTION_MOVE becomes ACTION_CANCEL and is passed to MyView. Note that when we receive the ACTION_CANCEL message, it means that the control will not receive further messages.

As you can see, the second and subsequent ACTION_MOVE never passes MyView.

ACTION_UP event transmission

Consistent with the second and subsequent ACTION_MOVE transfer flow.

5.2 Intercepting ACTION_MOVE Events at dispatchTouchEvent

In addition to intercepting ACTION_MOVE events in onInterceptTouchEvent, you can also intercept ACTION_MOVE events in dispatchTouchEvent. Modify the code for InnerViewGroup as follows, intercepting ACTION_MOVE in dispatchTouchEvent and leaving the rest of the events as default.

override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
    when(ev.action) {
        MotionEvent.ACTION_MOVE -> {
            return true
        }
    }
    return super.dispatchTouchEvent(ev)
}
Copy the code

OnTouchEvent in MyView still returns true.

override fun onTouchEvent(ev: MotionEvent): Boolean {
    return true
}
Copy the code

The following is the result of the event passing.

TestActivity: dispatchTouchEvent: action = ACTION_DOWN
OuterViewGroup: dispatchTouchEvent: action = ACTION_DOWN
InnerViewGroup: dispatchTouchEvent: action = ACTION_DOWN
MyView: dispatchTouchEvent: action = ACTION_DOWN
MyView: onTouchEvent: action = ACTION_DOWN

TestActivity: dispatchTouchEvent: action = ACTION_MOVE
OuterViewGroup: dispatchTouchEvent: action = ACTION_MOVE
InnerViewGroup: dispatchTouchEvent: action = ACTION_MOVE

TestActivity: dispatchTouchEvent: action = ACTION_UP
OuterViewGroup: dispatchTouchEvent: action = ACTION_UP
InnerViewGroup: dispatchTouchEvent: action = ACTION_UP
MyView: dispatchTouchEvent: action = ACTION_UP
MyView: onTouchEvent: action = ACTION_UP
Copy the code
Event Distribution Flow Chart

The flow chart for intercepting ACTION_MOVE events in dispatchTouchEvent is as follows.

ACTION_DOWN event delivery

Since there is no interception of the ACTION_DOWN event, the ACTION_DOWN message is passed to MyView.

ACTION_MOVE event passing

Because ACTION_MOVE is intercepted in ViewGroup2’s dispatchTouchEvent, ACTION_MOVE passing to ViewGroup2 stops. Unlike the onInterceptTouchEvent ACTION_MOVE in ViewGroup2, MyView does not receive an ACTION_CANCEL message.

ACTION_UP event transmission

Since there is no interception of the ACTION_UP event, the ACTION_DOWN message is passed to MyView.

conclusion

  1. You can generally intercept ACTION_MOVE messages in onInterceptTouchEvent and dispatchTouchEvent, but make sure the ACTION_MOVE message is delivered to the interception.
  2. When you want to process ACTION_MOVE messages, experienced engineers will tell you to return true in the control’s onTouchEvent. As you can see from Section 3, ACTION_MOVE can be passed to the control. But notice that the outer layer of the control does not block ACTION_MOVE.

At this point, this article is all over, I believe that readers must have a new understanding of View event distribution.

Write in the last

If you are interested in me, please go to blogss.cn or follow programmer Xiabei to learn more.

  • If this article has helped you, please feel free to like it and follow it. This is what keeps me writing ❤️
  • Due to the author’s limited level, if there are any mistakes in this article, please correct them in the comments section ✔️
  • This article was first published in nuggets. Reprint is prohibited without permission ©️