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
- 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.
- 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
DecorView
extendsFrameLayout
extendsViewGroup
The real logic of dispatchTouchEvent is in the ViewGroup
ViewGroup.java
Appeal Code:ACTION_DOWN
The 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.
canceled
Check whether the event is cancelled and whether the event is intercepted by the upper layer
You can see whenintercept
Is false andcanceled
Is iterated through the for loopViewGroup
thechild
And then calldispatchTransformedTouchEvent()
If thedispatchTransformedTouchEvent()
If the return value is true, calladdTouchTarget()
. And when theintercept
If it is true, it will not iterateViewGroup
thechild
And will not callchild
thedispatchTransformedTouchEvent()
.
To givedispatchTransformedTouchEvent()
thechild
Don’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.
ifmFirstTouchTarget
fornull
, to calldispatchTransformedTouchEvent()
.
Unfinished…