1.Activity

Window (PhoneWindow) ->DecorView (FrameLayout) ->ViewGroup

  • dispatchTouchEvent
    • Return True/False Touch The event is consumed
    • Return super normal distribution Touch events – > ViewGroup. DispatchTouchEvent
    • Window.superDispatchTouchEvent
      • DecorView.superDispatchTouchEvent
  • onTouchEvent
    • The return True Touch event is consumed

2.ViewGroup

  • MFirstTouchTarget (TouchTarget)The event is consumed without NULL
    • Child (View) The child View object to be touched
    • PointerIdBits (int) ID of a touch
    • Next (TouchTarget) the next TouchTarget
  • requestDisallowInterceptTouchEvent(boolean disallowIntercept)
    • Ture does not allow interception
    • False Allow interception
  • dispatchTouchEvent

    • Return false Does not consume events and is passed back (parent onTouchEvent). Subsequent events are not passed to this View
    • Return True The event is consumed
    • The return super result is determined by onTouchEvent
    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
    • Check whether ViewGroup is required to intercept Touch events
      • ACTION_DOWN
      • mFirstTouchTarget! =null indicates that the ViewGroup did not intercept the Touch event and the child View consumed the Touch
      • MFirstTouchTarget ==null indicates that the ViewGroup intercepts the Touch event or that the subview does not consume the Touch even though the ViewGroup does not intercept the Touch event. Anyway, you need the ViewGroup itself to handle the Touch event
    if (! canceled && ! intercepted) { ... / / this event is Down or the second finger touch screen events or for mouse events, here only study Donw events if (actionMasked = = MotionEvent. ACTION_DOWN | | (split && actionMasked = = MotionEvent.ACTION_POINTER_DOWN) || actionMasked == MotionEvent.ACTION_HOVER_MOVE) { ... if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) { //1 ... }}}... if (mFirstTouchTarget == null) { // 2 handled = dispatchTransformedTouchEvent(ev, canceled, null, TouchTarget.ALL_POINTER_IDS); } else { ... //3 if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) { handled = true; } else { ... if (dispatchTransformedTouchEvent(ev, cancelChild, target.child, target.pointerIdBits)) { handled = true; }... }... }Copy the code
    • dispatchTransformedTouchEvent
      • The event DOWN and not intercepted is called 1, which is distributed to the child for View processing
      • The event that is not consumed by the child’s View will be called 2, which will be handled by the current onTouchEvent and not distributed further down
      • The Down event is consumed by the child’s View, and subsequent events call 3; The Down event is not called
      if (child == null) {
            handled = super.dispatchTouchEvent(event);
      } else {
            handled = child.dispatchTouchEvent(event);
      }
    Copy the code
  • onInterceptTouchEvent

    • Return false/super Does not intercept
    • Return true intercepts mFirstTouchTarget== NULL and the touch event is handed to the onTouchEvent of the current ViewGroup
  • onTouchEvent

    • Return super/false does not consume events, passes back (parent onTouchEvent), subsequent events are not passed to this ViewGroup
    • Return True The event is consumed

3.View

  • dispatchTouchEvent
    if (li ! = null && li.mOnTouchListener ! = null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) { result = true; } if (! result && onTouchEvent(event)) { result = true; }Copy the code
    • OnTouchListener is not empty and onTouch returns true, then the event is consumed and not passed to OnTouchEvent
    • Return false does not consume events, passes backwards, and subsequent events are not passed to this View
    • Return True The event is consumed
    • Results of the return super OnTouchListener. The onTouch/onTouchEvent decision
  • onTouchEvent
    • Return super/false does not consume events, passes backwards, and subsequent events are not passed to this View
    • Return True The event is consumed

The interview questions

The event is passed by Activity_diapatchTouchEvent — >Window: PhoneWindow_diapatchTouchEvent — >DecorView: FrameLayout_diapatchTouchEvent — >ViewGroup_diapatchTouchEvent — >ViewGroup_diapatchTouchEvent – > View_diapatchTouchEvent – > View_onTouchEvent – > ViewGroup_onTouchEvent -… – > Activity_onTouchEvent.

When an Activity receives an event, it asks its child View whether it can consume it. If the child View is a ViewGroup, it determines whether it can intercept it:

  • If you intercept onTouchEvent consumption given to yourself;
  • If it is not intercepted, the query will continue until the specific child View, and finally the View’s onTouchEvent consumption;
  • OnTouchEvent: The event is consumed and the event ends. The event is not consumed and is returned to the parent onTouchEvent consumption, after which the sequence of events will not be passed to the View for processing