Introduction to Android's Touch event handling mechanism

  • 2020-05-05 13:16:28
  • OfStack

Android's Touch event handling mechanism is complex, especially after considering multi-touch and event interception.
Android's Touch event handling is divided into three layers: Activity layer, ViewGroup layer and View layer.
Let's start with a few basic rules for handling Touch events.
If the ACTION_DOWN event is not handled at a certain level, the layer will not receive subsequent Touch events until the next ACTION_DOWN event.

description:
a. When a level does not handle an event, it means that it and its child View do not handle the event.
b. This rule does not apply to the Activity layer (which is the top layer), which can receive every Touch event.
c. There will be no impact if incidents such as ACTION_MOVE are not addressed.

If the ACTION_DOWN event occurs within the scope of an View, subsequent ACTION_MOVE, ACTION_UP, ACTION_CANCEL events will be sent to the View, even if the event is already out of bounds.
The first pressed finger triggers ACTION_DOWN, the next pressed finger triggers ACTION_POINTER_DOWN, the middle pressed finger triggers ACTION_POINTER_UP, and the last pressed finger triggers ACTION_UP (even if it is not the finger that triggered ACTION_DOWN).

pointer id can be used to track the finger, and pointer id takes effect from the moment the finger is pressed until the moment it gets up.
If an ACTION_DOWN event is intercepted by the parent View, no child View will receive any more Touch events (this meets the requirements of point 1).
If a non-ACTION_DOWN event is intercepted by the parent View, the child View that last handled the ACTION_DOWN event will receive an ACTION_CANCEL event and will not receive any Touch events later, even if the parent View no longer intercepts subsequent Touch events.

If the parent View decides to handle the Touch event or the child View does not handle the Touch event, then the parent View handles the Touch event as normal View, otherwise it does not handle the Touch event at all (it is only responsible for distribution).
If the parent View intercepts the event in onInterceptTouchEvent, the Touch event will no longer be received in onInterceptTouchEvent, and the event will be left to itself (as normal View would).
The details are layered below.

1.Activity layer:

public boolean dispatchTouchEvent(MotionEvent ev) { 
if (ev.getAction() == MotionEvent.ACTION_DOWN) { 
onUserInteraction(); 
} 
if (getWindow().superDispatchTouchEvent(ev)) { // I'll hand it over here View Layer handles  
return true; 
} 
return onTouchEvent(ev); //  if View The layer is not processed, so it is processed here  
}

2.View layer:

public boolean dispatchTouchEvent(MotionEvent event) { 
//  Some details were omitted  
ListenerInfo li = mListenerInfo; 
if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 
&& li.mOnTouchListener.onTouch(this, event)) { 
return true; 
} 
if (onTouchEvent(event)) { 
return true; 
} 
return false; 
}

View has more onTouch method code, and the main logic is divided into two steps: first, pass the event to TouchDelegate for processing (if any), and then handle it by itself if TouchDelegate does not handle it; Mainly responsible for the transformation of View state (such as press down state), long press event, click event detection and trigger.

3.ViewGroup layer (more complex) :
The overall logic of ViewGroup layer handling Touch events is as follows: firstly, check whether interception is needed. If there is no interception, send it to child View for processing. If child View is not processed, then handle it by itself.
The logic of interception is that all events between down and up are considered as a set of events. If the events are intercepted from down, the subsequent events in the group are completely left to themselves, and there is no need to enter the interception logic. If you intercept from the middle, you send the cancel event to child View first, and the subsequent events in the group are completely left to yourself, without having to enter the interception logic.

The distribution logic is that when ACTION_DOWN event, find child View for processing, called find Target; If Target is not found, handle by yourself; If Target is found, it is left to Target.
From the code point of view, dispatchTouchEvent is responsible for the distribution logic, and onTouchEvent is responsible for the real processing logic.

Related articles: