編輯: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 布局文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- <com.touchstudy.LayoutView2
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:gravity="center">
- <com.touchstudy.MyTextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/tv"
- android:text="AB"
- android:textSize="40sp"
- android:textStyle="bold"
- android:background="#FFFFFF"
- android:textColor="#0000FF"/>
- </com.touchstudy.LayoutView2>
- </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 。
眾所周知,一般情況下我們使用android中的monkeyrunner進行自動化測試時,使用的是python語言來寫測試腳本。不過,最近發現可以用java調用mo
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
在使用eclipse進行安卓java的編程的時候,有時候我們會遇到這樣的問題:那就是無故彈出aapt.exe停止工作的提示,雖然程序不會崩潰,但是這個提示經常彈出
前言 之前因為項目需求,其中使用到了圖片的單擊顯示取消,圖片平移縮放功能,昨天突然想再加上圖片的旋轉功能,在網上看了很多相關的例子,可是沒看到能同時實現我想要的功