(未完)Android 點擊事件響應總結

一、從Activity/Dialog到DecorView

Activity或Dialog先響應到dispatchTouchEvent()事件,拿Activity爲例

public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    return onTouchEvent(ev);
}

Called to process touch screen events. You can override this to intercept all touch screen events before they are dispatched to the window. Be sure to call this implementation for touch screen events that should be handled normally.
其中,getWindow()返回的是Activity的mWindow對象,其被初始化爲PhoneWindow

mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);

插一段介紹setCallback()方法,它的參數爲Window.Callback接口,裏面有一些常用的方法,比如

public boolean dispatchTouchEvent(MotionEvent event);

Called to process touch screen events. At the very least your implementation must call superDispatchTouchEvent(MotionEvent) to do the standard touch screen processing.
boolean Return true if this event was consumed.

public void onWindowFocusChanged(boolean hasFocus);

This hook is called whenever the window focus changes. See View.onWindowFocusChangedNotLocked(boolean) for more information.

public void onAttachedToWindow();

Called when the window has been attached to the window manager. See View.onAttachedToWindow() for more information.

public void onDetachedFromWindow();

Called when the window has been attached to the window manager. See View.onDetachedFromWindow() for more information.

回到Activity的dispatchTouchEvent(MotionEvent)方法,它調用了PhoneWindow的superDispatchTouchEvent(MotionEvent)方法

@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
    return mDecor.superDispatchTouchEvent(event);
}

mDecor是DecorView類型的變量,看下它的superDispatchTouchEvent()方法

public boolean superDispatchTouchEvent(MotionEvent event) {
    return super.dispatchTouchEvent(event);
}

調用了它的父類(FrameLayout)的父類(ViewGroup)的dispatchTouchEvent(MotionEvent)方法。
再次回到Activity的dispatchTouchEvent()方法,如果事件未被消耗(getWindow().superDispatchTouchEvent(ev)返回false),則會調用Activity的onTouchEvent(MotionEvent)方法。

二、從DecorView到ContentView

2.1 先說下PhoneWindow與DecorView的關係

PhoneWindow中DecorView類型變量爲mDecor,它的初始化在installDecor()中

    private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);
            ...  
        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

            // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
            mDecor.makeOptionalFitsSystemWindows();
            ... 
            }
        }
    }            

其中,generateDecor(int)方法創建了DecorView對象

    protected DecorView generateDecor(int featureId) {
        ...
        return new DecorView(context, featureId, this, getAttributes());
    }

調用了DecorView的構造方法

    DecorView(Context context, int featureId, PhoneWindow window,
            WindowManager.LayoutParams params) {
        super(context);
        ...
        setWindow(window); // 將PhoneWindow保存到DecorView的mWindow變量中
        ...
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章