Event Delivery Mechanism

Method:

  • dispatchTouchEvent: Distribute events.If true is returned, it means that the event has been processed after distribution; if false, it means that no View has been processed after distribution
  • onInterceptTouchEvent intercepts events.Returning true indicates an interception event; returning false indicates no interception.This intercepts events that would otherwise be passed to child controls, so this method is unique to ViewGroup.
  • onTouchEvent handles events.If true is returned, the event is handled; if false is returned, the event is not handled.

Some conclusions about the mechanism of event delivery:

  • activity has no onInterceptTouchEvent method because it is an event source and interception is meaningless
  • view has no onInterceptTouchEvent method because it is a leaf node and interception is meaningless
  • The onInterceptTouchEvent method in the viewgroup returns false by default (no interception), unless it is overridden and returns true;
	//ViewGroup.java
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.isFromSource(InputDevice.SOURCE_MOUSE)
                && ev.getAction() == MotionEvent.ACTION_DOWN
                && ev.isButtonPressed(MotionEvent.BUTTON_PRIMARY)
                && isOnScrollbarThumb(ev.getX(), ev.getY())) {
            return true;
        }
        return false;
    }
  • View ontouchEvent consumes events by default (returns true), unless it is clickable (or long Clickable is also false).View's long Clickable property is false by default, clickable property is case-sensitive, such as Button's clickable property is true by default, TextView's clickable property is false by default (true means consuming the event, false means not consuming the event)
  • The event delivery process is outward-inward, that is, the event is always passed to the parent element before it is distributed to the child element. The request DisallowInterceptTouchEvent method can intervene in the event distribution process of the parent element in the child element, except for ACTION_DOWN events.

Pseudo-code for dispatchTouchEvent method of ViewGroup

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean consume = false;
        if(onInterceptTouchEvent(ev)){//Whether or not to intercept, the onTouchEvent method of the current control is intercepted
            consume = onTouchEvent(ev);
        }else{//Call the child control distribution method without intercepting; and so on, until the event is consumed
            consume = child.dispatchTouchEvent(ev);
        }
        return consume;
    }

Distribution process:
The ViewGroup first determines whether it needs this event when it is distributed, and if it needs to, it returns true on the onInterceptTouchEvent, intercepts the event, and calls the onTouchEvent method of the current viewgroup.
If this event is not needed, the distribution of child controls is invoked, and so on, until the event is consumed.
If the onTouchEvent of the current control returns false, the current event is not consumed, and the parent control's amount onTouchEvent is then called.
If the onTouchEvent of the current control returns true, indicating consumption of the current event, the event terminates

Overall event transfer process: from outside to inside, then from inside to outside, until the event is consumed

Event conflict resolution:

  • External interception (parent controls are handled according to business logic, and child views do not intercept events when they need to be handled by child views)
	//The pseudocode for the parent control logic is as follows
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;//Default No Interception
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                intercepted = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if(The current container needs this click event){
                    intercepted = true;
                }else{//This click event is not required for the current container
                    intercepted = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercepted = false;
                break;
            default:
                break;
        }
        return intercepted;
    }
  • Internal interception (child controls handle events according to business logic, requesting parent controls not to intercept event requestDisallowInterceptTouchEvent when events are needed, and requesting parent controls to intercept events when events are not needed)

1. Control interception logic through dispatchTouchEvent in child controls

	//The code to control logic in the child control is as follows:
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);//Request parent control not to intercept
                break;
            case MotionEvent.ACTION_MOVE:
                if(Parent control requires this event){
                    getParent().requestDisallowInterceptTouchEvent(false);//Let the parent control handle the event
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
            default:
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

2. The parent control cannot intercept ACTION_DOWN events, because ACTION_DOWN events are not controlled by the flag bit FLAG_DISALLOW_INTERCEPT, so once the parent control intercepts ACTION_DOWN events, none of them can be passed to the child elements.

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        if(action == MotionEvent.ACTION_DOWN){
            return false;
        }else{
            return true;
        }
    }

Reference resources
Exploration of the Art of android Development

Keywords: Java Android

Added by ScotDiddle on Fri, 02 Aug 2019 04:20:22 +0300