Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> android 事件分發 攔截 (onInterceptTouchEvent dispatchTouchEvent onTouchEvent)

android 事件分發 攔截 (onInterceptTouchEvent dispatchTouchEvent onTouchEvent)

編輯:關於android開發

android 事件分發 攔截 (onInterceptTouchEvent dispatchTouchEvent onTouchEvent)


Touch事件分發中只有兩個主角:ViewGroup和View。Activity的Touch事件事實上是調用它內部的ViewGroup的Touch事件,可以直接當成ViewGroup處理。View在ViewGroup內,ViewGroup也可以在其他ViewGroup內,這時候把內部的ViewGroup當成View來分析。

 

ViewGroup的相關事件有三個:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。

View的相關事件只有兩個:dispatchTouchEvent、onTouchEvent。

先分析ViewGroup的處理流程:首先得有個結構模型概念:ViewGroup和View組成了一棵樹形結構,最頂層為Activity的ViewGroup,下面有若干的ViewGroup節點,每個節點之下又有若干的ViewGroup節點或者View節點,依次類推。如圖:

\

當一個Touch事件(觸摸事件為例)到達根節點,即Acitivty的ViewGroup時,它會依次下發,下發的過程是調用子View(ViewGroup)的dispatchTouchEvent方法實現的。簡單來說,就是ViewGroup遍歷它包含著的子View,調用每個View的dispatchTouchEvent方法,而當子View為ViewGroup時,又會通過調用ViwGroup的dispatchTouchEvent方法繼續調用其內部的View的dispatchTouchEvent方法。上述例子中的消息下發順序是這樣的:①-②-⑤-⑥-⑦-③-④。dispatchTouchEvent方法只負責事件的分發,它擁有boolean類型的返回值,當返回為true時,順序下發會中斷。在上述例子中如果⑤的dispatchTouchEvent返回結果為true,那麼⑥-⑦-③-④將都接收不到本次Touch事件。

 

話說還是上代碼驗證,寫過了就

 


 

ViewGroup的dispatchTouchEvent是真正在執行“分發”工作,而View的dispatchTouchEvent方法,並不執行分發工作,或者說它分發的對象就是自己,決定是否把touch事件交給自己處理,而處理的方法,便是onTouchEvent事件.

 

 

public class Btn extends Button {
    public Btn(Context context) {
        super(context);
    }

    public Btn(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public Btn(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.i("Btn","dispatchTouchEvent "+ev.getAction()+"");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i("Btn","onTouchEvent "+event.getAction()+"");
        return super.onTouchEvent(event);
    }

}
\

 

 

\
 

\
main.xml

\

 

\

日志都添加完畢,現在我們點擊btn 看看執行順序.

\

可見默認情況下 viewgroup會通過dispatchTouchEvent一直向下分發事件. dispatchTouchEvent 過程中調用onInterceptTouchEvent看viewgroup自己會不會對事件進行攔截.
先是down 然後是up.直到葉子節點view 時候調用其onTouchEvent 然後 在down的時候調用 onclicklistener.

 

現在我們來驗證dispatchTouchEvent 返回值對事件分發的影響. 正常情況dispatchTouchEvent 默認為super.dispatchTouchEvent .return true; 則事件不再往底層傳遞.而ontouch 事件也應該由改view 或者viewgroup的來消費.

測試ONE (btnLinerLayout的dispatchTouchEvent 分別 返回 false 和 true)

false 情況:

\可以看到down事件在btnLinerLayout 停止分發了. (btn dispatchTouchEvent 沒執行) , 事件首先被rootLinerLayout的onTouchEvent處理 然後 返回給上級的TestActivity onTouchEvent處理. 最後一個onTouchEvent 被定為後續事件的處理著,up 事件就 直接交給TestActivity來處理.

有一點不明白: TestActivity的onTouchEvent 執行完後 btn的onclickListener 不執行了 ,||

true 情況:

 

\true 就與預想的一樣 事件不在往底層傳遞.並且沒有地方消費onTouchEvent...||

這時候如果btnLinerLayout onTouchEvent 返回true 則上層的onTouchEvent 會被依次執行. down直接則直接交給TestActivity.

如果單獨把btnLinerLayoutonTouchEvent 返回true.【dispatchTouchEvent 為super】 則結果和默認的一樣.事件最後傳遞給Btn 葉子節點消費.執行其onTouchEvent 並且down的時候直接把事件交給btn的onTouchEvent 並且執行 onClickLlistener

 

總結 只要dispatchTouchEvent 不為super 那麼就會中斷事件的傳遞.只不過false的情況 事件的響應父級會默認一次往上都響應到onTouchEvent裡面. 並且隨後的up事件會直接交給頂層目標來處理. true的話事件也會依次回傳但是都不響應.

 

測試two(BtnLinerLayout的onInterceptTouchEvent 返回 true ,dispatchTouchEvent 為 super | true | false):

正常情況.onInterceptTouchEvent 返回true 代表事件被當前viewgroup攔截,和消費

 

dispatchTouchEvent 默認super():

\BtnLinerLayout執行順序為dispatchTouchEvent-onInterceptTouchEvent -onTouchEvent 的確自己能處理onTouchEvent了.並且依次傳遞給上層的onTouchEvent

 

dispatchTouchEvent 為 true

\事件被攔截 並且 沒有繼續下發.到BtnLinerLayout 截至了.

dispatchTouchEvent 為 false

\事件被攔截.沒有繼續下發.當前也沒有消費 一次交由父類 onTouchEvent響應. 最後 事件交由頂層的TestActicty onTouchEvent執行 後續down事件直接轉給 TestActivity

。。。這情況和直接設置為dispatchTouchEvent 為false onInterceptTouchEvent 為默認一樣.向上傳遞相應 默認都執行onTouchEvent.

 

由上面2輪測試可以看出

 

onInterceptTouchEvent 為true . 事件會被當前的viewgruop消費到onTouchEvent中.默認情況下依次響應到父類的onTouchEvent中.最後到頂層.隨後的up事件直接交給頂層處理.

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved