Android View, ViewGroup event distribution

Although I have read the relevant information all the time, and used a lot, but I still remember it, I hope everyone can understand that
View inherits
Drawable.Callback,
KeyEvent.Callback,
AccessibilityEventSource

ViewRootImpl
frameworks/base/core/java/android/view/ViewRootImpl.java

View
frameworks/base/core/java/android/view/View.java

Event delivery (first acquired by the outermost view)

ViewGroup - ViewGroup - view

Method
event dispatch in View

public boolean dispatchTouchEvent(MotionEvent ev)  

Event interception (returns false by default)

public boolean onInterceptTouchEvent(MotionEvent ev)

Event handling (default returns false)

public boolean onTouchEvent(MotionEvent ev)

* The combination of default distribution and processing is like a closed loop*
1
1.1 Enter the dispatchTouchEvent of the topmost parent View for event distribution

true to handle by itself (enter onTouchEvent)
false enter (method onInterceptTouchEvent) to see if the event is intercepted
If interception returns true - (enter this View onTouchEvent)
do not intercept return false - (pass to child View)

1.2 The same judgment of sub-Views

1.3 If the View finds that it has no child View, it will handle it by itself.

2
2.1 If the onTouchEvent of the child View

Return false (do not process) onTouchEvent The event will be passed to the parent View and accepted by the parent View's onTouchEvent
Return true (do not process) It will be handed over to its own onTouchEvent for processing

  1. When a view intercepts and handles onTouchEvent

1. How does the source view get the event message
1.1 View initialization

public class View implements Drawable.Callback, KeyEvent.Callback,
        AccessibilityEventSource {

// 初始化
 public View(Context context, AttributeSet attrs, int defStyle) {

//
 View() {
        mResources = null;
    }

1.2 Obtaining attachInfo

  /**
     * @param info the {@link android.view.View.AttachInfo} to associated with
     *        this view
     */
    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
        //System.out.println("Attached! " + this);
        mAttachInfo = info;
        mWindowAttachCount++;
        // We will need to evaluate the drawable state at least once.
        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
        if (mFloatingTreeObserver != null) {
            info.mTreeObserver.merge(mFloatingTreeObserver);
            mFloatingTreeObserver = null;
        }
        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
            mAttachInfo.mScrollContainers.add(this);
            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
        }
        performCollectViewAttributes(mAttachInfo, visibility);
        onAttachedToWindow();

        ListenerInfo li = mListenerInfo;
        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
                li != null ? li.mOnAttachStateChangeListeners : null;
        if (listeners != null && listeners.size() > 0) {
            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
            // perform the dispatching. The iterator is a safe guard against listeners that
            // could mutate the list by calling the various add/remove methods. This prevents
            // the array from being modified while we iterate it.
            for (OnAttachStateChangeListener listener : listeners) {
                listener.onViewAttachedToWindow(this);
            }
        }

        int vis = info.mWindowVisibility;
        if (vis != GONE) {
            onWindowVisibilityChanged(vis);
        }
        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
            // If nobody has evaluated the drawable state yet, then do it now.
            refreshDrawableState();
        }
        needGlobalAttributesUpdate(false);
    }

1.3 Get ViewRootImpl

    /**
     * Gets the view root associated with the View.
     * @return The view root, or null if none.
     * @hide
     */
    public ViewRootImpl getViewRootImpl() {
        if (mAttachInfo != null) {
            return mAttachInfo.mViewRootImpl;
        }
        return null;
    }

1.4 View's dispatchPointerEvent (this is the key point of passing in), get dispatchTouchEvent and get MotionEvent

  public final boolean dispatchPointerEvent(MotionEvent event) {
        if (event.isTouchEvent()) {
            return dispatchTouchEvent(event);
        } else {
            return dispatchGenericMotionEvent(event);
        }
    }

1.5 Next dispatchTouchEvent will be passed to other

    public boolean dispatchTouchEvent(MotionEvent event) {
        if (mInputEventConsistencyVerifier != null) {
//=======================================================            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
        }

        if (onFilterTouchEventForSecurity(event)) {
            //noinspection SimplifiableIfStatement
            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;
            }
        }

        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
        }
        return false;
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325921023&siteId=291194637