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 ViewmFirstTouchTargetMost 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,mFirstTouchTargetTo null. Calls itselfonTouchEvent()Try consuming yourself, if not, events will not be passed on later. (Because for the upper layer of ViewGroupA,mFirstTouchTargetNull)

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….

I am a fresh graduate, recently and friends maintain a public account, the content is that we in the transition from fresh graduate to the development of this way stepped on the pit, as well as our step by step learning records, if interested in friends can pay attention to it, together with fuel ~