Detailed explanation of Android touch event distribution process

This paper describes the event distribution process of Android touch in the form of examples, which is very helpful for in-depth understanding and mastering Android programming. The specific analysis is as follows:

First, start with a simple example:

Let's take a look at an example, as shown in the figure below:

Layout file:

Mainactivity file:

When the user clicks the button, the following log will be output:

We can see that the dispatchtouchevent method in the activity is executed first, then the ontouch method is executed, then the dispatchtouchevent -- > ontouch, and finally the button click event is executed. Here we may have a question: Why did dispatchtouchevent and ontouch execute twice, while onclick only executed once? Why are the actions of two touch events different? What exactly do action 0 and action 1 represent?

Friends who have overwritten ontouchevent know that generally speaking, we will process concentrated touch type events in this method, including action_ DOWN、ACTION_ MOVE、ACTION_ Up, etc., but in our example above, it does not move, but simply press and lift. Therefore, our touch events only press and lift, so there are two touch events, and the action is 0 and 1 respectively. Let's look at some variable definitions in motionevent:

It can be seen that the press event is 0 and the lift event is 1, which also confirms what we said above.

I'm looking at two other scenarios:

1. Click the area outside the button to output the log as follows:

2. We return true in the ontouch function, and the output log is as follows:

Why are these two scenarios like this? Let's move on.

Android touch event distribution

What is the process of event distribution?

Simply put, when users touch the mobile phone screen, a touch message will be generated. Finally, the touch message will be transmitted to the InputHandler of viewroot (when looking at the source code of 4.2, this class is changed to viewrootimpl). Viewroot is the bridge between GUI management system and GUI presentation system. According to the definition of viewroot, it is found that it is not a view type, but a handler. InputHandler is an interface type used to handle events of keyevent and touchevent types. Let's look at the source code:

After layers of fog, whether the Mview at code 7 is a decorview or the root view of the non window interface, its essence is ViewGroup, that is, the touch event is finally distributed by the root view ViewGroup!!! Let's take activity as an example to analyze this process. We know that the displayed activity has a top-level window. The implementation class of this window is phonewindow. The content area in phonewindow is a view of decorview type. This view is the content we see on the mobile phone. This decorview is a subclass of FrameLayout, The dispatchtouchevent of activity is actually calling the dispatchtouchevent of phonewindow. Let's look at the source code and enter the dispatchtouchevent function of activity:

As you can see, if the event is a press event, you will enter the onuserinteraction () function, which is empty. Let's ignore it for the time being. Continue to see that the distribution of touch events calls the getwindow(). Superdispatchtouchevent (EV) function. The type of instance obtained by getwindow() is phonewindow type. You can view the type obtained by getwindow() in your activity class in the following way:

Output:

OK, no more nonsense. Let's continue to watch the superdispatchtouchevent function in phonewindow.

Well, the superdispatchtouchevent (event) function of mdecor is called. This mdecor is the decorview type we mentioned above, that is, a top-level ViewGroup of all contents on the activity we see, that is, the root node of the whole viewtree. Look at its statement.

DecorView

So let me continue to see what decorview is.

It can be seen that decorview inherits from FrameLayout. Its distribution (dispatchtouchevent) and processing of touch events are handled by super class, that is, FrameLayout. We don't see the corresponding implementation in FrameLayout. We continue to track to the parent class of FrameLayout, ViewGroup. We see the implementation of dispatchtouchevent, Let's first look at how ViewGroup (Android 2.3 source code) distributes events.

Touch event distribution for ViewGroup

The code of this function is relatively long. We only look at the key points marked above. First, you can see a condition judgment in code 1, if disallowaintercept and! If one of onintercepttuchevent (EV) is true, it will enter this condition judgment. Disallowintercept refers to whether the event interception function is disabled. The default value is false. This value can also be modified by calling the requestdisallowintercepttuchevent method. Then, when the first value is false, it will completely rely on the second value to determine whether it can enter the interior of condition judgment. What is the second value? Onintercepttouchevent is a function of ViewGroup to intercept events. If the function returns false, it means that the event is not intercepted, otherwise it means that the event is intercepted. The second condition is to negate the return value of the onintercepttuchevent method, that is, if we return false in the onintercepttuchevent method, we will make the second value true, so as to enter the interior of the condition judgment. If we return true in the onintercepttuchevent method, we will make the whole of the second value false, Thus jumping out of this conditional judgment. For example, if we need to realize the function of sliding and deleting an item in listview, we can realize this function by returning true in onintercepttuchevent and implementing relevant judgment logic in ontuchevent.

After entering the if in code 1, there is a for loop that traverses all child views under the current ViewGroup. If the coordinates of the touch event are within the coordinates of a child view, the child view will process the touch event, that is, call the dispatchtouchevent of the child view. If the child view is of ViewGroup type, continue to perform the above judgment and traverse the child views; If the child view is not of ViewGroup type, the dispatchtouchevent method in the view is called directly, unless the child view type overrides the method. Let's look at the dispatchtouchevent function in view:

Touch event distribution for view

In this function, first judge whether the event complies with the security policy, then judge whether the view is enabled, and whether the touch listener is set, which is set through setontouchlistener.

If montouchlistener.ontouch (this, event) returns false, continue to execute ontouchevent (event); If montouchlistener.ontouch (this, event) returns true, it means that the event has been consumed and will not be delivered. Therefore, ontouchevent (event) will not be executed. This also verifies scenario 2 left above. When the ontouch function returns true, the button is clicked, but our click event is not executed. So let's take a look at what the ontouchevent (event) function does first.

As we can see, in the ontouchevent function, it is action_ UP、ACTION_ DOWN、ACTION_ Move and other events are processed, and the most important event is the up event, because it includes the processing of user click events, or it is relatively important for users, so it is placed in the first case. In action_ In the up event, we will judge whether the view is enabled, clickable and whether the focus is obtained. Then we see that a performclick object will be delivered to the UI thread through the post method. If the delivery fails, we will directly call the performclick function to execute the click event.

Let's look at the performclick class.

You can see that it wraps the performclick () method in the view class. Look at the performclick () method again:

The code is very simple. It mainly calls monclicklistener. Onclick (this); Method, that is, execute the click event processing listener set by the user through setonclicklistener. summary

The user touches the screen to generate a touch message. The bottom layer of the system forwards the message to viewroot (viewrootimpl), and viewroot generates a dispatch_ The message of pointer, and the message is processed in handlemessage. Finally, the message will be processed through deliverpointerevent (motionevent event). In this function, mview.dispatchtouchevent (event) will be called to distribute messages. This Mview is a ViewGroup type, so it is the dispatchtouchevent (event) of ViewGroup. In this function, all child views will be traversed, and the left side of the trigger of the event will be found and compared with the coordinates of each child view. If the touched coordinates are within the range of the child view, It is processed by the child view. If the child view is of ViewGroup type, continue the search process in the previous step; Otherwise, execute the dispatchtouchevent (event) function in view. In the dispatchtouchevent (event) of view, first judge whether the control is enabled and whether the mtouchlistent is empty. If the mtouchlistener is not empty, execute the mtouchlistener.ontouch (event) method. If the method returns false, then execute the ontouchevent (event) method in view, and execute the monclicklistener.onclick (this, event) in the method; method; If montouchlistener.ontouch (event) returns true, the ontouchevent method will not be executed, so the click event will not be executed.

The rough flow chart is as follows:

I believe this article has a certain reference value for you to further master Android programming.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>