深刻Android開發之--Android事件模型

 前言: java

   通常咱們處理事件,都是針對某一個View來處理了,要麼是添加onTouchListener監聽器,要麼繼承View而後重寫View#onTouchEvent, android

甚至不用重寫,只要使用Widget本身的監聽函數 ,或者GestureDetector就OK了. ide

可是理解Android事件模型,對於理解GestureDetector,及Android事件的交互,寫出具備出色的交互的應用. 函數

都是必經之路. this


一:ViewGroup與View的事件模型 spa

 咱們都知道Android界面實際是一棵View的樹.枝幹是ViewGroup. code

ViewGroup繼承自View,可是又是管理View的容器.那麼ViewGroup與View的事件關係是怎麼樣的呢? orm

這須要從另外一個重要的ViewGroup中的方法,以下提及: 繼承

public boolean onInterceptTouchEvent(MotionEvent ev) {
        return false;
 }
它的默認實現很簡單,就是把事件交給子View去處理.本身不攔截.

Intercept就是攔截的意思. 事件

此方法的註釋,對於ViewGroup與View的事件模型說得很清楚,

主要是如下幾點:

(1) 若是此方法返回false,說明此ViewGroup暫時(只是暫時)對於觸控事件不感興趣.

 可是不知道後面的事件它感不感興趣.因此後續事件還會一直傳遞到此方法中來,供此方法判斷.

(2) 若是此方法返回true了.那麼說明此方法對應的ViewGroup開始對於此事件(或者手勢)感興趣了.

 那麼後續事件就會直接給此方法對應的ViewGrouponTouchEvent方法來處理事件了.

(3) 若是此方法一開始返回false,說不感興趣這個時候事件發給了目錄View.

   如今又返回true,說感興趣了.那麼目錄View就會收到一個action爲ACTION_CANCEL的事件.

    跟此方法返回true時的事件是同一個事件 ,只是action變了.

(4) ViewGroup會在這裏接收觸控開始的事件.


規則就是上面這些 ,那麼是誰在後面處理這些規則呢?

就是ViewGroup.它在disptachTouchEvent方法中,進行了一系列的處理來實現這種模型.

 public boolean dispatchTouchEvent(MotionEvent ev)


 對於單獨的View自己來講,它也有一個簡單的事件派發模型.經過如下代碼就能夠很明白的看出來了:


View#dispatchTouchEvent(MotionEvent event):

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;
}


 二: Activity與View的事件模型

   事件先到Activity中,而後Activity調用:

/**
     * 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.
     * 
     * @param ev The touch screen event.
     * 
     * @return boolean Return true if this event was consumed.
     */
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }
 來分發事件, 這裏的邏輯是:

 先讓用戶界面窗口處理:getWindow().superDispatchTouchEvent(ev)

 若是窗口沒有處理這個事件.

 那就交給Activity本身處理.return onTouchEvent(ev)

這個Window跟View層級是怎麼交互的呢?

 咱們找到了Window的實現類:PhoneWindow(com.android.internal.policy.impl.PhoneWindow)

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

這個mDecor就是用戶界面的根View了.

  private final class DecorView extends FrameLayout

(com.android.internal.policy.impl.PhoneWindow.DecorView)

原來窗口將事件交給根View來進行事件派發的.

mDecor調用本身的superDispatchTouchEvent(event)

而後將事件派發的任務交給了本身的dispatchTouchEvent

public boolean superDispatchTouchEvent(MotionEvent event) {
            return super.dispatchTouchEvent(event);
}
這裏調用的super.dispatchTouchEvent 就是ViewGroup的聲明的dispatchTouchEvent的了.
相關文章
相關標籤/搜索