(未完)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变量中
        ...
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章