preface
Here first to everyone apologize! Why are we still talking about event distribution? Because I can’t! In fact, there was a serious mistake. I don’t know how much trouble I brought to my friends. That’s what I said in my last article that the TouchTarget of the current View records the View that consumes the current event. That’s not true!
So today’s article is first of all about error correction, and second is a thorough review of what TouchTarget actually refers to and the whole process of event distribution.
The body of the
If the current View’s mFirstTouchTarget is not null, then the current TouchEvent event, It is distributed directly to the View recorded in the mFirstTouchTarget (that is, the dispathTouchEvent() that called the View).
So if mFirstTouchTarget is the View that consumes the event, then the event will be distributed directly from the root View to the View that consumes the event, that is, the event will skip all views at the intermediate level (” no middleman earns the difference “). But I guess any of you who have experience will know that this is not going to go beyond the View in the middle.
Yes, in fact that assumption is wrong!
The Log face
ViewGroupB is nested in ViewGroupA, ViewGroupB is nested in ViewC. All distribution methods return the implementation of super directly, except ViewC’s onTouchEvent() method, which returns true. At this point we click and slide ViewC…
ViewGroupA -> dispatchTouchEvent -> MotionEvent.ACTION_DOWN
ViewGroupA -> onInterceptTouchEvent -> MotionEvent.ACTION_DOWN
ViewGroupB -> dispatchTouchEvent ->MotionEvent.ACTION_DOWN
ViewGroupB -> onInterceptTouchEvent -> MotionEvent.ACTION_DOWN
ViewC -> dispatchTouchEvent -> MotionEvent.ACTION_DOWN
ViewC -> onTouchEvent -> MotionEvent.ACTION_DOWN
ViewGroupA -> dispatchTouchEvent -> MotionEvent.ACTION_MOVE
ViewGroupA -> onInterceptTouchEvent -> MotionEvent.ACTION_MOVE
ViewGroupB -> dispatchTouchEvent ->MotionEvent.ACTION_MOVE
ViewGroupB -> onInterceptTouchEvent -> MotionEvent.ACTION_MOVE
ViewC -> dispatchTouchEvent -> MotionEvent.ACTION_MOVE
ViewC -> onTouchEvent -> MotionEvent.ACTION_MOVE
ViewGroupA -> dispatchTouchEvent -> MotionEvent.ACTION_UP
ViewGroupA -> onInterceptTouchEvent -> MotionEvent.ACTION_UP
ViewGroupB -> dispatchTouchEvent ->MotionEvent.ACTION_UP
ViewGroupB -> onInterceptTouchEvent -> MotionEvent.ACTION_UP
ViewC -> dispatchTouchEvent -> MotionEvent.ACTION_UP
ViewC -> onTouchEvent -> MotionEvent.ACTION_UP
We see that Touch events are passed level by level in the View hierarchy. Therefore, we can draw a conclusion:
On the current ViewmFirstTouchTarget
Most likely, it is the View that may consume events in its child View.
The Debug and verification
Next, let’s break to dispathTouchEvent() on ViewGroupA to see what it is:
Indeed, the mFirstTouchTarget of the current View is the View that records the hit consumption event in its child View.
So based on this result, the flow of event distribution is really strung together!
In the last article we saw that the logic for event distribution is all done in the dispatchTouchEvent() of the root View. Limiting the scene to ViewGroupA->ViewGroupB->ViewC, let’s see how the distribution is done.
comb
The event DOWN comes to ViewGroupA’s dispatchTouchEvent(). Since onInterceptTouchEvent() returns false, the event’s x and y are passed to sub-views that match the scope to continue distributing the event. But at this point no one knows who can consume this event.
Once the child View is found (that is, ViewGroupB), call dispatchTouchEvent() of ViewGroupB. For ViewGroupA, the return value of dispatchTouchEvent() from ViewGroupB will determine whether any View consumes the event.
- If true is returned, the event is successfully distributed and mFirstTouchTarget is logged as ViewGroupB, which handles all subsequent events.
- If false is returned, this event has no View consumption,
mFirstTouchTarget
To null. Calls itselfonTouchEvent()
Try consuming yourself, if not, events will not be passed on later. (Because for the upper layer of ViewGroupA,mFirstTouchTarget
Null)
ViewGroupB’s dispatchTouchEvent() is also a duplicate of the intercept, but it is also not intercepted, and then the event is sent to its child View’s dispatchTouchEvent() by X and Y, which is ViewC.
ViewGroupB is also waiting for the return value of ViewCdispatchTouchEvent() to determine its mFirstTouchTarget.
Since ViewC is a View, its dispatchTouchEvent() return value depends on its own onTouchEvent(). Because our ViewC consumes the event, that is, onTouchEvent() returns true. So ViewC’s dispatchTouchEvent() also returns true.
So ViewGroupB’s dispatchTouchEvent() returns true, knowing that the event was consumed by ViewC, then mFirstTouchTarget records ViewC, and subsequent events are known to be dispatched to ViewC by ViewGroupB. So VIewGroupB’s dispatchTouchEvent() returns true.
In the same way, ViewGroupA knows that it can distribute events to itself to VIewGroupB…
In this way, subsequent MVOE, UP events can be smoothly distributed layer by layer.
conclusion
Therefore, there are some problems that we can explain through the source code:
Problem 1: ViewGroupBonInterceptTouchEvent()
Returns true, butonTouchEvent()
What happens if you return false?
If the current View intercepts an event, its dispatchTouchEvent() return value will depend on the child’s onTouchEvent(). So false is returned. So VewGroupB’s dispatchTouchEvent() returns false.
So for ViewGroupA at this point, the event is not distributed in the child View, so ViewGroupA tries to consume, and if onTouchEvent() itself returns false, subsequent events will not be distributed.
Problem 2: In ViewGroupBdispatchTouchEvent()
What happens if you just return true without dropping any methods?
We know that VewGroup and the implementation of dispatchTouchEvent() in View are the keys to actually distributing events. If dispatchTouchEvent() in our ViewGroupB returns true. For VewGroupA, directly to the ViewGroupB subsequent events, that is ViewGroupBdispatchTouchEvent () without any method, So for ViewGroupB it will not call onInterceptTouchEvent() and onTouchEvent() except for the dispatchTouchEvent() callback.
The end of the
These two articles really sort out the basic process of event distribution. It is recommended that you look at a source code with your own articles…
A follow-up interview question about the event is definitely not going to stump you… (Haha, there is still a CANCEL event to be filled later.)
OK, guys, if you think the article is good… I have a small request, I want to eat the chicken leg….