“This is the 10th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

preface

We know that there is an interception mechanism for event distribution

onInterceptTouchEvent
Copy the code

When it returns true the event is not distributed down, otherwise it is distributed down.

But in the process, there is also a participant: requestDisallowInterceptTouchEvent, this function directly affect the interception of events. We’re going to talk about that today how this function affects event distribution.

Source code analysis

Let’s look at the source of this function first

@Override public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) ! = 0)) { // We're already in this state, assume our ancestors are too return; } if (disallowIntercept) { mGroupFlags |= FLAG_DISALLOW_INTERCEPT; } else { mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT; } // Pass it up to our parent if (mParent ! = null) { mParent.requestDisallowInterceptTouchEvent(disallowIntercept); }}Copy the code

You can see that it changes a switch, FLAG_DISALLOW_INTERCEPT, while calling its parent function.

So what does this switch do?

At the beginning of the ViewGroup dispatchTouchEvent function there is this code:

final boolean intercepted; if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget ! = null) { final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) ! = 0; if (! disallowIntercept) { intercepted = onInterceptTouchEvent(ev); ev.setAction(action); // restore action in case it was changed } else { intercepted = false; } } else { // There are no touch targets and this action is not an initial down // so this view group continues to intercept touches. intercepted = true; }Copy the code

If it is a Down event or mFirstTouchTarget is not null, it enters a code segment; Set interception to true if no.

We know that in the down event distribution process, if there is a child View consumption event, it will be assigned to the mFirstTouchTarget, and subsequent events will be directly distributed to the mFirstTouchTarget

You can also see here that if a child View consumes a Down event, the mFirstTouchTarget is not null, so subsequent events will also check for interceptions.

If there is no child view consumption event in the Down event, then the interception of subsequent events will be true. So subsequent events don’t iterate over the subView.

Now look at the if code snippet

The FLAG_DISALLOW_INTERCEPT switch, also known as disallowIntercept, is used at the outset

If disallowIntercept is true, it does not intercept. If not, judge onInterceptTouchEvent

So simply requestDisallowInterceptTouchEvent is set to true can skip onInterceptTouchEvent, not intercept events.

And because requestDisallowInterceptTouchEvent calls a function of the parent, so no longer intercept all levels of the parent view.

So requestDisallowInterceptTouchEvent function is to make the view, and above all the parent view of interception, and even onInterceptTouchEvent to true.

So we generally use it as follows

view.getParent().requestDisallowInterceptTouchEvent(true);
Copy the code

No parent view at any level of the view will intercept the event.

Expand the thinking

Let’s think about it a little bit more. In this case, the onInterceptTouchEvent is set before the touch event occurs, which is our usual usage. But what if this function is called during an event?

For example, in an event on The View’s onTouch

getParent().requestDisallowInterceptTouchEvent(true)
Copy the code

When events began handing out, down into the parent view dispatchTouchEvent event, which is the view has not been events, so there is no set requestDisallowInterceptTouchEvent.

At this moment if the parent view onInterceptTouchEvent returns true, the interception, view the incident is not distributed to, so requestDisallowInterceptTouchEvent never be executed, the view in other parts of the event.

But what if the parent view onInterceptTouchEvent returns false, i.e. not intercept, events can be distributed to the view, requestDisallowInterceptTouchEvent execution, All subsequent events skip the parent view’s onInterceptTouchEvent

For example, the onInterceptTouchEvent code of the parent view is as follows

   public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                return false;
            case MotionEvent.ACTION_MOVE:  
                    return true;
            case MotionEvent.ACTION_UP:
                return true;
            default:
                break;
        }
        return false;   
    }
Copy the code

Down events are not intercepted, but Move and Up events are.

If the child view is used in the down event of onTouch

getParent().requestDisallowInterceptTouchEvent(true)
Copy the code

So down event delivered to the view, perform the requestDisallowInterceptTouchEvent, return the true at the same time. When a subsequent move or UP event is distributed to the parent view, the onInterceptTouchEvent is skipped because of the FLAG_DISALLOW_INTERCEPT tag.

So the move and up return values in onInterceptTouchEvent are invalid, because this function is no longer executed.

conclusion

Through the analysis of the above can know requestDisallowInterceptTouchEvent will let father view of interception, and effect and the up layer upon layer. At the same time we can also through some logic control, make requestDisallowInterceptTouchEvent role in some cases only.