一、自定義的控件幾乎都要用到觸摸事件,不交互怎麼響應,相關的事件處理函數由dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent,處理這些事件的由view,viewGroup,和activityandroid
解釋:雖然view能夠dispatch和intercept,可是若是view是最小單元,那麼就無法使用這兩個方法了.函數
二、一個簡單的activity,contentview以下佈局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </RelativeLayout>
它的view層次以下所示:測試
三、對touch的派發規律spa
(1)interceptTouchEvent定義是否截取Touch消息,若在GroupView中想要處理Touch消息必須覆蓋此方法3d
(2)消息在dispatch過程當中,若子view的dispatchTouchEvent返回true,父view再也不處理這個消息code
(3)viewGroup的interceptTouchEvent一但返回true,消息將再也不派發給子view。xml
四、實例測試:blog
(1)測試佈局:事件
<com.example.testtouch.MyRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:id="@+id/parent" tools:context=".MainActivity" > <com.example.testtouch.MyChildView android:id="@+id/child1" android:layout_width="50dp" android:layout_height="50dp" android:background="#0000ff" /> <View android:layout_width="200dp" android:layout_height="200dp" android:background="#00ff00"/> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="點擊"/> </com.example.testtouch.MyRelativeLayout>
由此能夠繪製出view樹:
(2)對於dispatch事件:測試一:點擊viewgroup:
測試二:點擊MyChildView
測試三:在MyRelativeLayout中對dispatch事件返回true
測試四:在MyChildView中對dispatch返回true
對於dispatch事件:一直傳遞到最末端,若是
(3)對於onIntercept事件,測試一:MyRelativeLayout中對onIntercept事件返回false.
返回false後,當前控件再也不處理touch事件,調用子控件的dispatchTouch事件和子控件的touch事件
測試二:MyRelativeLayout中對onIntercept事件返回true.
返回true後,當前控件處理touch事件,並傳給上一上一層處理,touch的傳遞就會結束
(4)對於onTouch事件:測試一,MyRelativeLayout中OnTouch何時處理,最子元素MyChildView調用super.onTouchEvent(event)時候,
能夠看到,onTouch事件首先傳到最子元素,若是子元素調用super.onTouchEvent(event),會傳遞到父元素,並一層層往上傳
若是子元素的onTouch事件返回false
能夠看到,若是最裏層元素返回false,和上邊的處理同樣,就會調用父元素的onTouchEvent
若是子元素的onTouch事件返回true
返回true代表該元素對touch事件作了處理,父元素無需再處理,就再也不往上傳了。
測試二:MyRelativeLayout對onInterceptTouchEvent返回true,對touch事件進行截獲
對touch事件截獲以後,touch事件會在當前層進行處理,再也不傳忘子元素。
若是截獲後,當前層的onTouchEvent返回false
返回false後,自動調用上一層的onTouch事件。
若是截獲後,當前層的OnTouch事件返回true
當前層返回true後,代表當前層不但願父元素再進行處理touch事件,中斷了touch事件往父元素的路由。
總結:ViewGroup層處理Touch事件的整體邏輯是:先檢測是否須要攔截,沒有攔截的話下發給子View處理,若是子View沒有處理再自行處理,自行處理的邏輯與View同樣。