Android event distribution mechanism (upper) event distribution of ViewGroup

overview

The event distribution mechanism in Android is the distribution and processing of events by view and ViewGroup. There are many views inside the ViewGroup, and the ViewGroup inherits from the view, so the ViewGroup itself is also a view. Events can be distributed to its child views through the ViewGroup and handled by the child views, and the ViewGroup itself can also handle events. Let's analyze the distribution of time by ViewGroup in detail.

MotionEvent

When the finger touches the screen, a series of events are composed of the following three event types.   1. ACTION_ Down: press the screen with your finger 2. Action_ Move: move your finger on the screen 3. Action_ Up: the finger is lifted from the screen. For example, a simple screen touch action triggers a series of touch events: action_ DOWN->ACTION_ MOVE->…->ACTION_ MOVE->ACTION_ For the event distribution mechanism in Android, up refers to motionevent. The event distribution of view is also the distribution operation of motionevent. You can get the horizontal and vertical coordinates of the event relative to the upper left corner of the screen through getrawx and getrawy. Get the horizontal and vertical coordinates of the event relative to the upper left corner of the current view through getx() and gety().

Three important methods

public boolean dispatchTouchEvent(MotionEvent ev)

This is a method of event distribution. If an event is passed to the current view, the current view must call this method. The return type of dispatchtouchevent is Boolean. The return result indicates whether the event has been consumed. If the return is true, it indicates that the view has been consumed and will not be passed down.   

public boolean onInterceptTouchEvent(MotionEvent ev)

This method exists in the ViewGroup class and does not exist for the view class. Indicates whether to intercept an event. If the ViewGroup successfully intercepts an event, the event will not be passed down. For the same event sequence, if the current view successfully intercepts the event, the method will not be called again for subsequent events. The returned result indicates whether to intercept the current event. False is returned by default. Because a view is already at the bottom level, it will not have child controls, so there is no such method.   

public boolean onTouchEvent(MotionEvent event)

This method is called by dispatchtouchevent to process the event. The returned result is used to indicate whether the current event is consumed. If the current event is not consumed, the current view will not receive the event again in the same event sequence.   

View event distribution flowchart

For event distribution, let's take a look at the whole distribution process through a flowchart.

ViewGroup event distribution source code analysis

According to the above flow chart, now let's analyze the whole process of ViewGroup event distribution in detail. A series of events generated by sliding the finger on the touch screen. When the activity receives these events, it distributes the events by calling the activity's dispatchtouchevent method. Let's take a look at the dispatchtouchevent method of activity.

It can be seen from the method getwindow(). Superdispatchtouchevent (EV). At this time, the activity will hand over the event to window for processing. Window is an abstract class. Its concrete implementation has only one phonewindow, that is, at this time, the activity passes the event to the superdispatchtouchevent method in phonewindow. Now take a look at the superdispatchtouchevent code.

Mdecor in this is a decorview, which is a top-level view of an activity. It is an internal class of phonewindow, which inherits from FrameLayout. At this time, the event is handled by the superdispatchtouchevent method of decorview. Let's take a look at the superdispatchtouchevent method.

At this time, you can clearly see that decorview calls the dispatchtouchevent method of the parent class. As mentioned above, decorview inherits FrameLayout, which in turn inherits from ViewGroup. So at this time, the event starts to be handed over to the ViewGroup for processing. Now let's take a detailed look at the dispatchtouchevent method of the ViewGroup. Because the code of dispatchtouchevent is relatively long, some of the code will be extracted here for description.

As can be seen from the above code, in the dispatchtouchevent, the received event will be judged when the received action is received_ When the event is down, the target and status of event distribution will be cleared. Then execute the resettouchstate method to reset the touch state. Let's take a look at these two methods.

1. cancelAndClearTouchTargets(ev)

Let's first introduce mfirsttouchtarget, which is a touchtarget object. Touchtarget is an internal class of ViewGroup. Touchtarget uses a linked list data structure to store view. In this method, the main function is to empty the mfirsttouchtarget linked list and set mfirsttouchtarget to null.

2. resetTouchState()

Flag is introduced here_ DISALLOW_ The interrupt flag is a flag that prevents the ViewGroup from intercepting events. You can set this flag through the requestdisallowintercepttouchevent method. When this flag is set, the ViewGroup cannot intercept events except action_ Events other than down. As can be seen from the above code, when the event is action_ When down, the flag is reset_ DISALLOW_ Interpt tag. So let's go back to the dispatchtouchevent method again and continue to look at its source code.

This code mainly judges whether the event needs to be intercepted by ViewGroup. The following describes whether mfirsttouchtarget is null or not. When the event is not intercepted, after the child element of ViewGroup successfully processes the event, mfirsttouchtarget will be assigned and point to its child element. That is, mfirsttouchtarget at this time= null。 However, once the event is intercepted, mfirsttouchtarget will not be assigned, and mfirsttouchtarget will be null. In the above code, you can see that according to actionmasked = = motionevent. Action_ DOWN||mFirstTouchTarget!= Null to judge whether the event needs to be intercepted. For actionmasked = = motionevent.action_ The down condition is well understood. For mfirsttouchtarget= The two cases of null have been described above. For an event sequence, when the event is motionevent.action_ When down, the flag is reset_ DISALLOW_ Interpt, that is! Disallowintercept must be true, and the onintercepttouchevent method must be executed. The onintercepttouchevent method returns false by default. Therefore, when you need the ViewGroup to intercept events, you must override the onintercepttouchevent method and return true. One thing to note here is that for an event sequence, once an event in the sequence is successfully intercepted, the onintercepttouchevent method is executed, that is, the return value of onintercepttouchevent is true, then a series of events after the event are for the condition actionmasked = = motionevent.action_ DOWN||mFirstTouchTarget!= Null must be false, then the remaining series of events in the event sequence will be intercepted, and the onintercepttouchevent method will not be executed. Therefore, a conclusion is drawn here: for an event sequence, when one of the events is successfully intercepted, the remaining series of events will also be intercepted, and the onintercepttouchevent method will not be executed again. Next, let's take a look at how to handle the events that are not intercepted by the ViewGroup.

Although this code is relatively long, the logic in it is not very complex. First, get the number of child views and viewgroups in the current ViewGroup. Then step through the elements in the ViewGroup. After obtaining the child element in the ViewGroup, judge whether the element can receive touch events. If the child element can receive the touch event and the touch coordinate is within the visual range of the child element, it will continue to execute downward. Otherwise, continue. There are two criteria to measure whether the child element can receive the touch event: whether the child element is playing the animation and whether the coordinates of the click event are in the area of the child element. Once the child view receives the touch event, it starts to call the dispatchtransformedtouchevent method to distribute the event. There is a lot of code for the dispatchtransformedtouchevent method. Now only focus on the following five lines of code. As can be seen from the following five lines of code, the dispatchtouchevent of the child view will be called at this time, that is, at this time, the ViewGroup has completed the whole process of event distribution.

When the dispatchtouchevent of the child element returns true, that is, the child view successfully handles the event. At this time, mfirsttouchtarget will be assigned through the addtouchtarget method. If the dispatchtouchevent returns false, or if the current ViewGroup has no child elements, the following code will be called at this time.

Here, call the dispatchtransformedtouchevent method and set the child parameter to null. That is, the super. Dispatchtouchevent (event) method is executed. Since ViewGroup inherits from view, the event is handled by the dispatchtouchevent of the parent class at this time. How the parent view handles events through dispatchtouchevent will be described in detail in the next article. Here we have finished the event distribution of ViewGroup. Along the way, it is not difficult to find that there is a Boolean return value for dispatchtouchevent. For this return value, when true is returned, it indicates that the current event has been processed successfully. If false is returned, it is generally because the event processing ontouchevent returns false. At this time, it will be handed over to its parent control for processing, and so on. If the processing fails all the time, it will eventually be handed over to the ontouchevent method of the activity for processing.

summary

Here, let's take a macro look at the distribution of events by the ViewGroup. When the ViewGroup receives an event sequence, it will first judge whether to intercept the event. If the event is intercepted, it will process the event by calling the dispatchtouchevent of the parent view. If this event is not intercepted, it will be distributed to the child view. If the ViewGroup does not have a child view, or if the child view fails to handle the event, the event will be handed over to the ViewGroup for processing. If the ViewGroup still fails to handle the event, the event will eventually be handed over to the activity for processing.

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support programming tips.

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
分享
二维码
< <上一篇
下一篇>>