This is the 24th day of my participation in the August Text Challenge.More challenges in August

introduce

When we click, long press, or swipe, we generate events that are encapsulated as motionEvents. The distribution mechanism is to pass an event from the screen to the View/ViewGroup of the application, which then consumes or ignores the event.

View inheritance

  1. Inheriting from a View can only handle events

Like ImageView, it inherits from the View and it has no child View, and when it encounters an event, it only has two choices to process the event or not to process the event.

  1. To distribute events, inherit from the ViewGroup

A ViewGroup is basically a container that contains child views that can distribute events,

Distributed object

When events are passed, they are controlled by the following three methods:

  • DispatchTouchEvent: dispatches events
  • OnInterceptTouchEvent: Intercepts the event
  • OnTouchEvent: Consumption event

The process of event distribution

The event distribution mechanism uses a chain of responsibility design. If no component handles the event from the Activity to the View at the lowest level, the event is passed back to the Activity in turn.

Event flow chart

graph TD A[Avtivity#diapthchTouchEvent] --> B[PhoneWindow#superDispatchTouchEvent] B --> C - > D C [DecorView# superDispatchTouchEvent] [ViewGroup# dispatchTouchEvent] D - > | processing | events F [View# dispatchTouchEvent] -- > F  G[View#onTouchEvent]

Event distribution source code analysis

Acticity.java

The child View gets priority, because when the parent View decides not to intercept the child View, it calls dispatchTouchEvent, and the ViewGroup method will first iterate over the dispatchTouchEvent that called the child View. If both return false, This event is passed back to the Activity in turn.

Looking down will come back to understand this sentence.

public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();// Empty implementation, lock screen related
        }
	// There is only one instance of Window, PhotoWindow
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }
Copy the code

Avtivity in the call Window. SuperDispatchTouchEvent (ev), but not in the Window class superDispatchTouchEvent () method, PhotoWindow exists in this method as only one instance of Window.

PhoneWindow.java

public boolean superDispatchTouchEvent(MotionEvent event) {
    return mDecor.superDispatchTouchEvent(event);
}
Copy the code

PhoneWindow calls the DecorView. SuperDispatchTouchEvent ()

DecorView

public boolean superDispatchTouchEvent(MotionEvent event) {
    return super.dispatchTouchEvent(event);
}
Copy the code

DecorViewextendsFrameLayoutextendsViewGroup

The real logic of dispatchTouchEvent is in the ViewGroup

ViewGroup.java Appeal Code:ACTION_DOWNThe event is definitely going to be handled by the ViewGroup, and the subview can’t intercept it becauseresetTouchState()therequestDisallowInterceptTouchEvent()Flag bit to be setreset.

Intercept means whether to intercept an event.

OnInterceptTouchEvent () initializes the Intercept. In most cases, onInterceptTouchEvent() returns false, but we can override onInterceptTouchEvent() to change its return value.

canceledCheck whether the event is cancelled and whether the event is intercepted by the upper layer

You can see wheninterceptIs false andcanceledIs iterated through the for loopViewGroupthechildAnd then calldispatchTransformedTouchEvent()If thedispatchTransformedTouchEvent()If the return value is true, calladdTouchTarget(). And when theinterceptIf it is true, it will not iterateViewGroupthechildAnd will not callchildthedispatchTransformedTouchEvent().

To givedispatchTransformedTouchEvent()thechildDon’t fornull, so we’re calling the child ViewdispatchTouchEvent().

If the child ViewdispatchTouchEvent()Returns true, then callsaddTouchTarget().

Adds finger-level touch events to the beginning of the list.

When the event is sent to the ViewGroup, the first call to child’s dispatchTouchEvent() is traversed. If child’s dispatchTouchEvent() returns true, the mFirstTouchTarget is assigned. Otherwise mFirstTouchTarget is null.

ifmFirstTouchTargetfornull, to calldispatchTransformedTouchEvent().

Unfinished…