In Android development, event distribution mechanism is an important Android knowledge system, understanding and familiar with the whole distribution mechanism is conducive to better analysis of various click sliding failure problems, better to expand the control of the event function and the development of custom controls, at the same time, event distribution mechanism is also one of the Android interview questions. Bonus points if you can draw some of the event distribution diagrams below on the spot. Without further ado, the event distribution mechanism is important.

Android event distribution stream ###

There are many blog posts on the Android event distribution mechanism online, but many of them are to write a Demo and post the output Log or take source code analysis, and then a bunch of notes and instructions, if you look at the heart is certainly a lot of harvest but it is really difficult to say the whole process and remember. Was once tried to remember the whole process, but a period of time and forget, finally analyze the problems and the flow of events to think, a diagram to explain and presentation clear a lot of, I according to the drawing below a event distribution flow diagram, description of events from a user’s click later, in the case of different function return value the final direction.

Note:

  • If you look closely, the diagram is divided into three layers: Activity, ViewGroup, and View from top to bottom
  • Events start with the white arrow in the upper left corner and are dispatched by the Activity’s dispatchTouchEvent
  • The top word of the arrow represents the method return value (return true, return false, return super.xxxxx(),super means to call the superclass implementation.
  • The dispatchTouchEvent and onTouchEvent boxes have the word “true—-> consume” in them, which means that if the method returns true, the event will be consumed and will not go anywhere else, and the event will terminate.
  • At present, all graph events are for ACTION_DOWN. We will analyze ACTION_MOVE and ACTION_UP at last.
  • The Activity dispatchTouchEvent in the previous diagram was wrong (figure fixed), only the return super.dispatchTouchEvent(ev) was further down, and the event returned true or false was consumed (aborted).

Looking closely at the whole diagram, we can draw several conclusions about the direction of the flow of events. 1. If the event is not interrupted, the entire event flow is a U-shaped graph. Let’s take a look at this graph to better understand the meaning of u-shaped graph.

So if we call the default implementation of the parent class with super instead of overwriting or changing the return value of the method in the control, the whole event flow should be down from the Activity—->ViewGroup– >View with the dispatchTouchEvent method, Until the leaf node (View) is reached, the onTouchEvent method is called from the bottom up from View >ViewGroup >Activity.

2, dispatchTouchEvent and onTouchEvent once return true, the event stops passing (reaches the destination) (no one receives the event again). As long as the event returns true, the event is not passed on. For a return true, we often say that the event is consumed. Consumed means that the event has reached this point and will not be passed on.

3, dispatchTouchEvent and onTouchEvent return false events are passed back to the parent control’s onTouchEvent processing.

See the dark blue line above. In cases where false is returned, events are passed to the parent control onTouchEvent.

  • Returning false for dispatchTouchEvent should mean: Events stop being passed and sent to the child View and start backtracking to the parent control (the parent control’s onTouchEvent starts being sent back from the bottom up until some onTouchEvent returns true). The event distribution mechanism is like recursion. Return False means that the recursion stops and the backtracking begins.
  • OnTouchEvent Return False is simpler, which simply does not consume the event and allows the event to continue flowing down and up in the direction of the parent control.

DispatchTouchEvent, onTouchEvent, onInterceptTouchEvent

The default implementation of these ViewGroup and View methods is to allow the entire event installation to complete in a U-shape, so return super.xxxxxx() will allow the event to complete the entire event flow path in a U-shape direction) without any changes, backtracking, or termination.

So if you see the method return super.xxxxx(), the next direction of the event is to go to the next u-shaped destination. If you remember the diagram above, you can quickly determine which function of which control is going to go next. Function of onInterceptTouchEvent

Intercept means Intercept, every time a ViewGroup does a distribution, Ask the interceptor if you want to intercept (that is, ask yourself if you want to handle the event yourself). If you want to handle the event yourself, return true in the onInterceptTouchEvent method and the onTouchEvent will be handled by yourself. If you don’t intercept the event, you will pass it down to the child control. Default is not to intercept, because the View also need to this event, so onInterceptTouchEvent interceptor return. Super onInterceptTouchEvent () and return false is the same, will not intercept, Events will continue to be passed to the dispatchTouchEvent of the child View.

6. The direction of the event flow when the dispatchTouchEvent methods of ViewGroup and View return super.dispatchTouchEvent().

So let’s take a look at the dispatchTouchEvent of the ViewGroup, and we said return True is the final pass. Return false is going back to the parent View’s onTouchEvent, and then how can a ViewGroup dispatch the event to its own onTouchEvent by dispatchTouchEvent? Return true and false don’t work, Only Interceptor intercepts events for its own onTouchEvent, so the super implementation of ViewGroup dispatchTouchEvent is to call onInterceptTouchEvent. So what happens when a View dispatchTouchEvent returns super.DispatchTouchEvent () where does that event go? Unfortunately, the View doesn’t have an interceptor. But by the same token return true is the end. Return false is a backtrace of the parent onTouchEvent, how to distribute the event to your own onTouchEvent handler, That can only return super dispatchTouchEvent, of the View class dispatchTouchEvent () method is the default implementation can help you call the View their own onTouchEvent method.

Having said so much, I don’t know if I have made it clear. Finally, I would like to summarize:

  • For dispatchTouchEvent, onTouchEvent, return True terminates the event. Return False is to trace back to the parent View’s onTouchEvent method.
  • If a ViewGroup wants to distribute its own onTouchEvent, it needs the onInterceptTouchEvent method return True to intercept the event.
  • ViewGroup blocker onInterceptTouchEvent default is not intercepted, so the return. Super onInterceptTouchEvent () = return false.
  • A View does not have an interceptor, so in order for a View to send events to its own onTouchEvent, the default implementation of dispatchTouchEvent (super) for a View is to send events to its own onTouchEvent.

The dispatchTouchEvent of the ViewGroup and View does event distribution, so the event can be distributed to four targets

Note: ——> represents what the event target needs to do. 1, their own consumption, the end of transmission. — — — — — — — > return true; ——-> call super.dispatchTouchEvent(). By default, onInterceptTouchEvent will be called. OnInterceptTouchEvent return True assigns the event to its onTouchEvent handler. ——> call super.dispatchTouchEvent() the default implementation will call onInterceptTouchEvent. OnInterceptTouchEvent return false It passes the event to the subclass. 4, do not pass to the child View, event termination down, events start backtracking, from the parent View onTouchEvent event from bottom to top back to execute each control onTouchEvent——->return false; Note: Since the View has no child views, we don’t need onInterceptTouchEvent to determine whether the control passes the event to the child View or intercepts it. So a View’s dispatchTouchEvent() calls super.dispatchTouchEvent() by default passes the event to its own onTouchEvent handler (equivalent to intercepting). The event distribution of the View does not have point 3 of the 4 goals mentioned above.

The onTouchEvent method of the ViewGroup and View is used to handle events, so the event can only be handled in two ways:

—–>return true; 2, continue to upload from the bottom, do not consume the event, the parent View can receive the event —–>return false; The default implementation of a View is non-consuming. So super = = false.

The onInterceptTouchEvent method of a ViewGroup has two cases for events:

1, intercept, give yourself onTouchEvent handler –>return true; —->return false,ViewGroup does not intercept by default, so super==false;

About ACTION_MOVE and ACTION_UP####

ACTION_MOVE and ACTION_UP are not the same as ACTION_DOWN. You return false when executing ACTION_DOWN. The next set of actions will no longer be executed. ACTION_MOVE and ACTION_UP events will only be received if the previous event (such as ACTION_DOWN) returns true. Many bloggers have said this, but what does it mean? Let’s look at the specific analysis below.

As mentioned above, events are continuously propagated down to the View if they are not interrupted, and then continuously propagated back to the Activity. DispatchTouchEvent and onTouchEvent can consume events by returning true to terminate event delivery. The onInterceptTouchEvent does not consume events. It acts as a fork that diverts ACTION_MOVE and ACTION_UP functions. You will receive ACTION_MOVE and other subsequent events. Let’s take a look at the specific trend of ACTION_MOVE events and ACTION_UP events in different scenarios and summarize the rules.

1. Our dispatchTouchEvent method in ViewGroup1 returns true to consume the event

ACTION_DOWN ends after (Activity dispatchTouchEvent) ——–> (ViewGroup1 dispatchTouchEvent), The event is consumed (the red arrow below codes the ACTION_DOWN event flow).

/ / print log Activity | dispatchTouchEvent - > ACTION_DOWN ViewGroup1 | dispatchTouchEvent - > ACTION_DOWN -- -- -- -- > consumptionCopy the code

What would ACTION_MOVE and ACTION_UP look like in this scenario

Activity | dispatchTouchEvent --> ACTION_MOVE 
ViewGroup1 | dispatchTouchEvent --> ACTION_MOVE
----
TouchEventActivity | dispatchTouchEvent --> ACTION_UP 
ViewGroup1 | dispatchTouchEvent --> ACTION_UP
----

Copy the code

The red arrows in the figure below represent the flow of ACTION_DOWN events and the blue arrows represent the flow of ACTION_MOVE and ACTION_UP events

2. Our dispatchTouchEvent on ViewGroup2 returns true to consume this event

Activity | dispatchTouchEvent --> ACTION_DOWN ViewGroup1 | dispatchTouchEvent --> ACTION_DOWN ViewGroup1 | OnInterceptTouchEvent -- > ACTION_DOWN ViewGroup2 | dispatchTouchEvent - > ACTION_DOWN consumption Activity -- -- -- -- > | dispatchTouchEvent --> ACTION_MOVE ViewGroup1 | dispatchTouchEvent --> ACTION_MOVE ViewGroup1 | onInterceptTouchEvent --> ACTION_MOVE ViewGroup2 | dispatchTouchEvent --> ACTION_MOVE ---- TouchEventActivity | dispatchTouchEvent --> ACTION_UP ViewGroup1 | dispatchTouchEvent --> ACTION_UP ViewGroup1 | onInterceptTouchEvent --> ACTION_UP ViewGroup2 | dispatchTouchEvent --> ACTION_UP ----Copy the code

The red arrow represents the flow of ACTION_DOWN events and the blue arrow represents the flow of ACTION_MOVE and ACTION_UP events

3. “dispatchTouchEvent” returns true from ViewGroup2. Similarly, dispatchTouchEvent that receives ACTION_DOWN receives ACTION_MOVE and ACTION_UP. So we can basically conclude that if dispatchTouchEvent returns true on a control, then functions that receive ACTION_DOWN will also receive ACTION_MOVE and ACTION_UP.

The red arrow represents the flow of ACTION_DOWN events and the blue arrow represents the flow of ACTION_MOVE and ACTION_UP events

5. Our onTouchEvent in ViewGroup 2 returns true to consume this event. The red arrow represents the flow of ACTION_DOWN events and the blue arrow represents the flow of ACTION_MOVE and ACTION_UP events

The red arrow represents the flow of ACTION_DOWN events and the blue arrow represents the flow of ACTION_MOVE and ACTION_UP events

The red arrow represents the flow of ACTION_DOWN events and the blue arrow represents the flow of ACTION_MOVE and ACTION_UP events

8. We return false in the View dispatchTouchEvent and true in the Activity onTouchEvent to consume the event. The red arrow represents the flow of ACTION_DOWN events and the blue arrow represents ACTION_MOVE and ACTION_UP Event direction

9. We return false from dispatchTouchEvent on View and true from onTouchEvent on ViewGroup 1 consume this event. The red arrow represents the flow of ACTION_DOWN and the blue arrow represents ACTION_MOVE And ACTION_UP events

10. We return false on dispatchTouchEvent in View and true on onTouchEvent in ViewGroup 2 consume this event. The red arrow represents the flow of ACTION_DOWN events The blue arrows represent the flow of ACTION_MOVE and ACTION_UP events

We return false for dispatchTouchEvent on ViewGroup2 and true for onTouchEvent on ViewGroup1. The red arrow represents the ACTION_DOWN event flow The blue arrows represent the flow of ACTION_MOVE and ACTION_UP events

12. We return true for onInterceptTouchEvent in ViewGroup2 and true for onTouchEvent in ViewGroup 1. The red arrow represents the flow of ACTION_DOWN events and the blue arrow represents the flow of ACTION_MOVE and ACTION_UP events

I’ve drawn a lot of pictures at once, but THERE are a couple of cases where I’m not going to draw any more, and I’m sure you see the pattern, for consuming events on onTouchEvent: In which View onTouchEvent returns true, ACTION_MOVE and ACTION_UP events are passed down from the View, but directly to their own onTouchEvent and end the event transmission process.

Summary of ACTION_MOVE and ACTION_UP: ACTION_MOVE and ACTION_UP will be sent down from the top (via dispatchTouchEvent) to the control where the ACTION_DOWN event is consumed (return true). If the ACTION_DOWN event is consumed at dispatchTouchEvent, then the event is stopped. If the ACTION_DOWN event is consumed at onTouchEvent, An ACTION_MOVE or ACTION_UP event is passed to the control’s onTouchEvent handler and the transfer ends.

** Tips: recently made a custom control, which did a lot of event distribution processing and interaction, I feel can be as a practice of this article, we can see the source event distribution related to the part of the code, may have more experience, link address: CalendarListView**