自定義view的事件分發

android中的每個ViewGroup的子類都具有三個和TouchEvent相關的方法:

1.public boolean dispatchTouchEvent(MotionEvent event)              這個方法用來分發TouchEvent

2.public boolean onInterceptTouchEvent(MotionEvent event)         這個方法用來攔截TouchEvent

3.public boolean onTouchEvent(MotionEvent event)                        這個方法用來處理TouchEvent

注意:不是所有的View的子類,只有可以向裏面添加View的控件才需要分發,比如TextView它本身就是最小的view了,所以不用再向它的子視圖分發了,它也沒有子視圖了,所以它沒有dispatch和Intercept,只有touchEvent。

舉一個簡單的例子:(一個activity,佈局中有一個button)

對button進行監聽

 button.setOnClickListener(new OnClickListener() {
     @Override
   public void onClick(View v) {
        Log.d("TAG", " onClick");
     }
});


button添加一個touch事件

 button.setOnTouchListener(new OnTouchListener() {
     @Override
    public boolean onTouch(View v, MotionEvent event) {
         Log.d("TAG", "onTouch " + event.getAction());
         return false;
     }
 });

執行結果如下:
onTouch  0  相當與down
onTouch  1  相當於up
onClick     點擊事件
由上面的結果可以看出來:事件傳遞的順序是先經過onTouch,再傳遞到onClick
當onTouch return false說明你還沒消費onTouch事件,在執行完你onTouch裏面的代碼之後,onTouch事件並沒有結束
當onTouch return true時說明此次事件被onTouch給消費掉了,不會繼續向下傳遞了

接着看dispatchTouchEvent的源碼

    /**
      * Pass the touch screen motion event down to the target view, or this
      * view if it is the target.
      * @param event The motion event to be dispatched.
      * @return True if the event was handled by the view, false otherwise.
      */
     public boolean dispatchTouchEvent(MotionEvent event) {
         if (!onFilterTouchEventForSecurity(event)) {
             return false;
        }
         if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
                 mOnTouchListener.onTouch(this, event)) {
            return true;
         }
         return onTouchEvent(event);
    }
1.OnTouchListener是在setOnTouchListener方法中設置的,事實上就是我們剛纔在Activity中設置的setOnTouchListener,也就是說只要我們給控件註冊了touch事件,mOnTouchListener就一定被賦值了

2.第二個條件是判斷控件是否是使能的,按鈕默認即使Enabled,所以爲true

3.第三個條件是關鍵,該條件會回調控件註冊touch事件時的onTouch方法,這裏關鍵就是看onTouch方法執行的返回值

還有一點要題型的是Touch事件的層級傳遞。如果給一個控件註冊了touch事件,每次點擊它的時候都會觸發一系列ACTION_DOWN,ACTION_MOVE,ACTION_UP等事件.如果你在執行ACTION_DOWN的時候返回了false,後面一系列其它的action就不會再得到執行了。簡單的說,就是當dispatchTouchEvent在進行事件分發的時候,只有前一個action返回true,纔會觸發後一個action。

發佈了25 篇原創文章 · 獲贊 10 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章