Android -- TouchEvent的分發和截獲方式


Android系統中的每個ViewGroup的子類都具有下面三個和TouchEvent處理密切相關的方法:

public boolean dispatchTouchEvent(MotionEvent ev)         // 這個方法用來分發TouchEvent

public boolean onInterceptTouchEvent(MotionEvent ev)         //這個方法用來攔截TouchEvent

public boolean onTouchEvent(MotionEvent ev)                 //這個方法用來處理TouchEvent

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

onInterceptTouchEvent(MotionEvent ev)方法是GroupView控件中特有的一個方法,我們可以實現這個方法來截獲所有的窗口點擊事件來根據事件的不同來對子控件或自身分發事件觸發。覆蓋這個方法時需要小心注意,因為它和View.onTouchEvent(MotionEvent)有着復雜的關系,我們使用是需要和View.onTouchEvent(MotionEvent)一同實現來達到正確的結果,事件觸發順序如下:

  1.你首先會在該方法中得到一個down事件。

        2.這個down事件會被得到處理,要么在這個GroupView中子控件的onTouchEvent()方法中,要么在GroupView自身的onTouchEvent()方法中。當我們在onTouchEvent()方法返回值中返回true的話,將會繼續看到后續的觸發事件(move、up等),要注意的是當我們在GroupView的onTouchEvent()事件返回值中返回false的話,該方法將不再捕獲后續的(move up)事件。

  3.如果在該方法返回值中返回false,down事件將根據控件樹結構從根節點向目標子控件的onTouchEvent()方法分發。

  4.如果在該方法返回值中返回true,那么你的子控件將獲取不到任何點擊事件。

  為證明上面所說的順序特點,下面通過測試代碼來觀察觀察:

public class MainActivity extends Activity {
      Group1 group1;
      Group2 group2;
      MyTextView myTv;
  
      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
         
         
         //--group1
         //----|
         //-------group2
         //---------|
         //------------myTv
         
         group1 = new Group1(this);
         group2 = new Group2(this);
         myTv = new MyTextView(this);
         group2.addView(myTv, new LayoutParams(LayoutParams.FILL_PARENT,
                 LayoutParams.FILL_PARENT));
         group1.addView(group2, new LayoutParams(LayoutParams.FILL_PARENT,
                 LayoutParams.FILL_PARENT));
         setContentView(group1);
     }
 }

分別重寫Group1和Group2的onInterceptTouchEvent和onTouchEvent方法,重寫MyTextView的onTouchEvent方法,最終得到的控件層次結構如下:  

1

1.在默認返回值情況下logcat輸出如下:

1

測試后可知默認情況下和所有方法返回值為false的結果一致,down事件的捕獲順序onInterceptTouchEvent先於onTouchEvent,由於onTouchEvent返回值為false,down事件沒被消化,后續的move和up事件沒有出現,同時逆序返回到父控件的onTouchEvent方法來捕獲,如下圖所示:  

1

2.所有onTouchEvent返回值為true情況下logcat輸出如下:

1

輸出結果可以看出子控件MyTextView消化了down事件,后續的move和up事件正常捕獲,由於down事件被消化,上層的onTouchEvent方法不執行,如下圖所示:(三箭頭分別指down、move、up事件)

1

既然如此,如果MyTextView中onTouchEvent方法返回為false,而group1和group2的onTouchEvent方法返回true的結果自然也就如下圖的順序了:

1

測試輸出結果證明了這一猜測順序,  

1

3.當某個GroupView中的onInterceptTouchEvent方法返回值為true情況下logcat輸出如下(如group2):

1

如果在該方法返回值中返回true,那么子控件將獲取不到任何點擊事件,轉而向自身的onTouchEvent方法轉發,如下圖所示:

1

如果onTouchEvent方法返回值都為true,那么根據規律結果就如下圖順序觸發:  

1

最后logcat的結果證實了這一猜測, 

1

根據這一順序規律我們便可復寫GroupView中的onInterceptTouchEvent來控制事件的響應者。

我是天王蓋地虎的分割線                                                             

 

 

 

  參考:http://blog.csdn.net/alexander_xfl/article/details/11056679

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM