天天看點

Android View,ViewGroup 事件分發

雖然一直原來也有看過相關方面的資料,并且用到的也不少了, 但是還是記一記吧, 希望大家都能明白了解

View 繼承

Drawable.Callback,

KeyEvent.Callback,

AccessibilityEventSource

ViewRootImpl

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

View

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

事件的傳遞(是由最外層的view 最先擷取到)

ViewGroup - ViewGroup - view

View中的方法

事件分發

public boolean dispatchTouchEvent(MotionEvent ev)  
           

事件攔截(預設傳回false)

public boolean onInterceptTouchEvent(MotionEvent ev)
           

事件處理(預設傳回false)

public boolean onTouchEvent(MotionEvent ev)
           

* 預設的分發 和處理結合起來,就類似是個閉環*

1

1.1 進入 最頂層父View 的 dispatchTouchEvent 進行事件分發

true 交給本身處理(進入onTouchEvent)

false 進入(方法onInterceptTouchEvent) 看是否攔截事件

如果攔截 傳回true - (進入本View onTouchEvent)

不攔截 傳回false - (傳給子View)

1.2 子View相同判斷

1.3 如果View發現自己沒有子View 時,則自己處理。

2

2.1 如果子View的 onTouchEvent

傳回false (既不做處理) onTouchEvent 事件會向父View傳遞,并由父View的onTouchEvent 接受

傳回true (做處理) 既交給自身的 onTouchEvent 處理

  1. 當某個view 攔截,并且處理onTouchEvent

1. 源碼 View 是如何獲得 事件消息的

1.1 view 的初始化

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

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

//
 View() {
        mResources = null;
    }
           

1.2 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) != ) {
            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() > ) {
            // 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) != ) {
            // If nobody has evaluated the drawable state yet, then do it now.
            refreshDrawableState();
        }
        needGlobalAttributesUpdate(false);
    }
           

1.3獲得 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 的 dispatchPointerEvent (這個就是傳進來的重點了),得到了 dispatchTouchEvent 獲得 MotionEvent

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

1.5接下來 dispatchTouchEvent ,會陸續傳給其他

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, );
        }
        return false;
    }
           

繼續閱讀