Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android入門:onInterceptTouchEvent和onTouchEvent調用時序詳解

Android入門:onInterceptTouchEvent和onTouchEvent調用時序詳解

編輯:Android開發實例

onInterceptTouchEvent () ViewGroup 的一個方法,目的是在系統向該 ViewGroup 及其各個 childView 觸發 onTouchEvent() 之前對相關事件進行一次攔截, Android 這麼設計的想法也很好理解,由於 ViewGroup 會包含若干 childView, 因此需要能夠統一監控各種 touch 事件的機會,因此純粹的不能包含子 view 的控件是沒有這個方法的,如 LinearLayout 就有, TextView 就沒有。  

onInterceptTouchEvent () 使用也很簡單,如果在 ViewGroup 裡覆寫了該方法,那麼就可以對各種 touch 事件加以攔截。但是如何攔截,是否所有的 touch 事件都需要攔截則是比較復雜的, touch 事件在 onInterceptTouchEvent() 和 onTouchEvent 以及各個 childView 間的傳遞機制完全取決於 onInterceptTouchEvent() 和 onTouchEvent() 的返回值。並且,針對 down 事件處理的返回值直接影響到後續 move 和 up 事件的接收和傳遞。  

關於返回值的問題,基本規則很清楚,如果 return true, 那麼表示該方法消費了此次事件,如果 return false ,那麼表示該方法並未處理完全,該事件仍然需要以某種方式傳遞下去繼續等待處理。

SDK 給出的說明如下:

·    You will receive the down event here.

·    The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.

·    For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().

·    If you return true from here, you will not receive any following events: the target view will receive the same event but with the action  ACTION_CANCEL , and all further events will be delivered to your onTouchEvent() method and no longer appear here.

 

由於 onInterceptTouchEvent() 的機制比較復雜,上面的說明寫的也比較復雜,總結一下,基本的規則是:

1.         down 事件首先會傳遞到 onInterceptTouchEvent() 方法

2.         如果該 ViewGroup 的 onInterceptTouchEvent() 在接收到 down 事件處理完成之後 return false ,那麼後續的 move, up 等事件將繼續會先傳遞給該 ViewGroup ,之後才和 down 事件一樣傳遞給最終的目標 view 的 onTouchEvent() 處理。

3.         如果該 ViewGroup 的 onInterceptTouchEvent() 在接收到 down 事件處理完成之後 return true ,那麼後續的 move, up 等事件將不再傳遞給 onInterceptTouchEvent() ,而是和 down 事件一樣傳遞給該 ViewGroup 的 onTouchEvent() 處理,注意,目標 view 將接收不到任何事件。

4.         如果最終需要處理事件的 view 的 onTouchEvent() 返回了 false ,那麼該事件將被傳遞至其上一層次的 view 的 onTouchEvent() 處理。

5.         如果最終需要處理事件的 view  的 onTouchEvent() 返回了 true ,那麼後續事件將可以繼續傳遞給該 view 的 onTouchEvent() 處理。

 

下面用一個簡單的實驗說明上述復雜的規則。視圖自底向上共 3 層,其中 LayoutView1 和 LayoutView2 就是 LinearLayout ,   MyTextView 就是 TextView :

對應的 xml 布局文件如下:

 

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:orientation="vertical" 
  4.     android:layout_width="fill_parent" 
  5.     android:layout_height="fill_parent" > 
  6.     <com.touchstudy.LayoutView2 
  7.         android:orientation="vertical" 
  8.         android:layout_width="fill_parent" 
  9.         android:layout_height="fill_parent" 
  10.         android:gravity="center"> 
  11.        <com.touchstudy.MyTextView   
  12.             android:layout_width="wrap_content" 
  13.             android:layout_height="wrap_content" 
  14.             android:id="@+id/tv" 
  15.             android:text="AB" 
  16.             android:textSize="40sp" 
  17.             android:textStyle="bold" 
  18.             android:background="#FFFFFF" 
  19.             android:textColor="#0000FF"/> 
  20.    </com.touchstudy.LayoutView2> 
  21. </com.touchstudy.LayoutView1> 

 

下面看具體情況:

1.         onInterceptTouchEvent() 處理 down 事件均返回 false onTouchEvent() 處理事件均返回 true

------------------------------------------------------------------------------------------------------------------------------

04-11 03:58:42.620: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_DOWN

04-11 03:58:42.620: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_DOWN

04-11 03:58:42.620: DEBUG/MyTextView(614): onTouchEvent action:ACTION_DOWN

04-11 03:58:42.800: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_MOVE

04-11 03:58:42.800: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_MOVE

04-11 03:58:42.800: DEBUG/MyTextView(614): onTouchEvent action:ACTION_MOVE

…… // 省略過多的 ACTION_MOVE

04-11 03:58:43.130: DEBUG/LayoutView1(614): onInterceptTouchEvent action:ACTION_UP

04-11 03:58:43.130: DEBUG/LayoutView2(614): onInterceptTouchEvent action:ACTION_UP

04-11 03:58:43.150: DEBUG/MyTextView(614): onTouchEvent action:ACTION_UP

------------------------------------------------------------------------------------------------------------------------------

這是最常見的情況, onInterceptTouchEvent 並沒有做任何改變事件傳遞時序的操作,效果上和沒有覆寫該方法是一樣的。可以看到,各種事件的傳遞本身是自底向上的,次序是: LayoutView1->LayoutView2->MyTextView 。注意,在 onInterceptTouchEvent 均返回 false 時, LayoutView1 LayoutView2 onTouchEvent 並不會收到事件 ,而是最終傳遞給了 MyTextView 。

 

2.       LayoutView1 onInterceptTouchEvent() 處理 down 事件返回 true

MyTextView onTouchEvent() 處理事件返回 true

------------------------------------------------------------------------------------------------------------------------------

04-11 03:09:27.589: DEBUG/LayoutView1(446): onInterceptTouchEvent action:ACTION_DOWN

04-11 03:09:27.589: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_DOWN

04-11 03:09:27.629: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE

04-11 03:09:27.689: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_MOVE

…… // 省略過多的 ACTION_MOVE

04-11 03:09:27.959: DEBUG/LayoutView1(446): onTouchEvent action:ACTION_UP

------------------------------------------------------------------------------------------------------------------------------

從 Log 可以看到,由於 LayoutView1 在攔截第一次 down 事件時 return true ,所以後續的事件(包括第一次的 down )將由 LayoutView1 本身處理,事件不再傳遞下去。

 

3.         LayoutView1 LayoutView2 onInterceptTouchEvent() 處理 down 事件返回 false

MyTextView onTouchEvent() 處理事件返回 false

LayoutView2 onTouchEvent() 處理事件返回 true

----------------------------------------------------------------------------------------------------------------------------

04-11 09:50:21.147: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_DOWN

04-11 09:50:21.147: DEBUG/LayoutView2(301): onInterceptTouchEvent action:ACTION_DOWN

04-11 09:50:21.147: DEBUG/MyTextView(301): onTouchEvent action:ACTION_DOWN

04-11 09:50:21.147: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_DOWN

04-11 09:50:21.176: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE

04-11 09:50:21.176: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE

04-11 09:50:21.206: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_MOVE

04-11 09:50:21.217: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_MOVE

…… // 省略過多的 ACTION_MOVE

04-11 09:50:21.486: DEBUG/LayoutView1(301): onInterceptTouchEvent action:ACTION_UP

04-11 09:50:21.486: DEBUG/LayoutView2(301): onTouchEvent action:ACTION_UP

----------------------------------------------------------------------------------------------------------------------------

可以看到,由於 MyTextView 在 onTouchEvent() 中 return false , down 事件被傳遞給其父 view ,即 LayoutView2 的 onTouchEvent() 方法處理,由於在 LayoutView2 的 onTouchEvent() 中 return true ,所以 down 事件傳遞並沒有上傳到 LayoutView1 。注意,後續的 move up 事件均被傳遞給 LayoutView2 onTouchEvent() 處理,而沒有傳遞給 MyTextView

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