Android事件分發機制之Activity(一)

Android事件分發機制的原理簡單講就是從用戶點擊屏幕開始,從屏幕上移動,最後擡起的過程,主要包括:按下(down)、移動(move)、擡起(up),將這些操作觸發的事件交給具體的View處理的過程。

事件分發包含的主要方法有:

1、dispatchTouchEvent(進行事件分發)

2、onInterceptTouchEvent(判斷是否攔截事件,此方法只在ViewGroup中)

3、onTouchEvent(處理事件)

事件分發的順序:Activity --> ViewGroup --> View

這篇主要講的是事件分發在Activity中的執行流程,具體結合源碼來看:

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

事件分發從Activity的dispatchTouchEvent開始,首先第一個if條件判斷是否是按下操作,一般事件分發都是從按下操作開始執行,進入onUserInteraction方法中可以看到裏面什麼都沒寫,但是從註釋上可以看出,用戶可以重寫這個方法,用來判斷用戶在此activity上是不是觸發了點擊操作。

再看第二個if條件,getWindow()指的就是Window對象,我們來看下這個對象的superDispatchTouchEvent方法

public abstract boolean superDispatchTouchEvent(MotionEvent event);

可以看到這是一個抽象方法,接下來直接看Window唯一的實現類PhoneWindow怎麼寫的這個方法

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

看到這裏,我們會想mDecor又是什麼呢?其實它就是DecorView,它裏面的實現是這樣的

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

最後我們查看super.dispatchTouchEvent可以發現,調用的是ViewGroup裏面的dispatchTouchEvent方法,由此我們可以知道事件從Activity傳遞到了ViewGroup,再回到剛纔Activity的dispatchTouchEvent方法看,如果第二個if條件返回了true,事件被消費,那麼不會執行Activity的onTouchEvent方法,事件分發到此結束,反之,如果返回的是false,事件沒有被消費,則會交給Activity的onTouchEvent方法處理。

再來看下Activity的onTouchEvent方法:

    public boolean onTouchEvent(MotionEvent event) {
        if (mWindow.shouldCloseOnTouch(this, event)) {
            finish();
            return true;
        }

        return false;
    }

if條件裏面調用了Window的shouldCloseOnTouch方法,如果此方法返回true,則會退出Activity並返回true,否則返回false,事件分發到此結束。我們看下Window的shouldCloseOnTouch方法源碼:

    public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
        if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
                && isOutOfBounds(context, event) && peekDecorView() != null) {
            return true;
        }
        return false;
    }

1)mCloseOnTouchOutsize是由android:windowCloseOnTouchOutside屬性值決定的;

2)如果是按下操作;

3)判斷點擊事件是否在context(當前Activity)之外,如果是返回true,否則返回false;

4)peekDecorView()返回的是PhoneWindow的mDecor

所以最後這個方法的意思是:如果android:windowCloseOnTouchOutside屬性爲true,並且當前觸摸事件是ACTION_DOWN,且該觸摸事件在Activity之外,同時Activity包含了視圖,則返回true,否則返回false。接到上面說的onTouchEvent方法,如果if條件返回true,則Activity退出,而這個返回值就是由shouldCloseOnTouch方法決定的。

到此,Activity的事件分發流程就結束了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章