onInterceptTouchEvent()是ViewGroup的一個方法,目的是在系統向該ViewGroup及其各個childView觸發onTouchEvent()以前對相關事件進行一次攔截,Android這麼設計的想法也很好理解,因爲ViewGroup會包含若干childView,所以須要可以統一監控各類touch事件的機會,所以純粹的不能包含子view的控件是沒有這個方法的,如LinearLayout就有,TextView就沒有。 html
onInterceptTouchEvent()使用也很簡單,若是在ViewGroup裏覆寫了該方法,那麼就能夠對各類touch事件加以攔截。可是如何攔截,是否全部的touch事件都須要攔截則是比較複雜的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各個childView間的傳遞機制徹底取決於onInterceptTouchEvent()和onTouchEvent()的返回值。而且,針對down事件處理的返回值直接影響到後續move和up事件的接收和傳遞。 java
關於返回值的問題,基本規則很清楚,若是return true,那麼表示該方法消費了這次事件,若是return false,那麼表示該方法並未處理徹底,該事件仍然須要以某種方式傳遞下去繼續等待處理。android
SDK給出的說明以下:app
因爲onInterceptTouchEvent()的機制比較複雜,上面的說明寫的也比較複雜,總結一下,基本的規則是:ide
下面用一個簡單的實驗說明上述複雜的規則。視圖自底向上共3層,其中LayoutView1和LayoutView2就是LinearLayout, MyTextView就是TextView:佈局
對應的xml佈局文件以下:this
<?xml version="1.0" encoding="utf-8"?>.net
<com.touchstudy.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"設計
android:orientation="vertical"rest
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>
下面看具體狀況:
------------------------------------------------------------------------------------------------------------------------------
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。
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自己處理,事件再也不傳遞下去。
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。
----------------------------------------------------------------------------------------------------------------
應你們的要求,我把源代碼貼上,其實很簡單,就是基礎文件,主要是用來觀察事件的傳遞。
主Activity: InterceptTouchStudyActivity.java:
public class InterceptTouchStudyActivity extends Activity {
static final String TAG = "ITSActivity";
TextView tv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layers_touch_pass_test);
}
}
LayoutView1.java:
public class LayoutView1 extends LinearLayout {
private final String TAG = "LayoutView1";
public LayoutView1(Context context, AttributeSet attrs) {
super(context, attrs);
Log.d(TAG,TAG);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
// return true;
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onTouchEvent action:ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"onTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG,"onTouchEvent action:ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");
break;
}
return true;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
LayoutView2.java:
public class LayoutView2 extends LinearLayout {
private final String TAG = "LayoutView2";
public LayoutView2(Context context, AttributeSet attrs) {
super(context, attrs);
Log.d(TAG,TAG);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG,"onInterceptTouchEvent action:ACTION_CANCEL");
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onTouchEvent action:ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"onTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG,"onTouchEvent action:ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");
break;
}
return true;
}
}
MyTextView.java:
public class MyTextView extends TextView {
private final String TAG = "MyTextView";
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.d(TAG,TAG);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
Log.d(TAG,"onTouchEvent action:ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"onTouchEvent action:ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.d(TAG,"onTouchEvent action:ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG,"onTouchEvent action:ACTION_CANCEL");
break;
}
return false;
}
public void onClick(View v) {
Log.d(TAG, "onClick");
}
public boolean onLongClick(View v) {
Log.d(TAG, "onLongClick");
return false;
}
}
轉至:http://www.blogjava.net/TiGERTiAN/archive/2011/02/22/344869.html