上一篇文章主要講述了Android的TouchEvent的分發過程,其中有兩個重要的函數:onInterceptTouchEvent和onTouchEvent,這兩個函數可被重裝以完成特定的邏輯。onInterceptTouchEvent的定義爲於ViewGroup中,默認返回值爲false,表示不攔截TouchEvent。onTouchEvent的定義位於View中,當ViewGroup要調用onTouchEvent時,會利用super.onTouchEvent。ViewGroup調用onTouchEvent默認返回false,表示不消耗touch事件,View調用onTouchEvent默認返回true,表示消耗了touch事件。考慮到onInterceptTouchEvent與onTouchEven在寫UI的時候常常會用到,下面以一個例子來說解一下。html
先建立一個類MyView,繼承自Viewjava
[java] view plaincopyandroid
public class MyView extends Button { ide
private static final String TAG = MyView.class.getName(); 函數
public MyView(Context context){ 佈局
super(context); spa
} .net
public MyView(Context context, AttributeSet attrs) { code
super(context, attrs); orm
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return super.onTouchEvent(event);
}
}
建立類MyLayout,繼承自ViewGroup
[java] view plaincopy
public class MyLayout extends FrameLayout{
private static final String TAG = MyLayout.class.getName();
public MyLayout(Context context) {
super(context);
}
public MyLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return super.onTouchEvent(event);
}
}
LogUtil.logAction()函數是用來打印MotionEvent的動做類型,代碼以下:
[java] view plaincopy
public class LogUtil {
public static void logAction(MotionEvent event, final String tag) {
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN:
Log.d(tag, "action down");
break;
case MotionEvent.ACTION_CANCEL:
Log.d(tag, "action cancel");
break;
case MotionEvent.ACTION_UP:
Log.d(tag, "action up");
break;
case MotionEvent.ACTION_MOVE:
Log.d(tag, "action move");
break;
default:
Log.d(tag, "unknow action");
}
}
}
佈局文件main.xml將MyView嵌套在MyLayout中,代碼以下:
[html] view plaincopy
<view android:layout_width="fill_parent"
android:layout_height="fill_parent"
class="com.example.AndroidTest.MyLayout" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view">
<com.example.AndroidTest.MyView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="hello" />
</view>
MainActivity的代碼以下:
[java] view plaincopy
public class MainActivity extends Activity {
public static final String TAG = "TouchDemoActivity";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
程序啓動後,截圖以下。
下面分狀況討論程序的運行結果。
一、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回true
狀況1:當點擊藍色框內的任意位置,只有MyLayout會接收事件,輸出的Log以下:
能夠看出,touch事件最後會被MyLayout的onTouchEvent接收到。
狀況2: 點擊紅色框內的黑色區域,因爲onInterceptTouchEvent()返回false,故MyView也能接收到touchEvent事件,輸出的Log以下:
能夠看出,因爲MyView的onTOuchEvent默認返回True,消耗了touch事件,MyLayout中的onTOuchEvent將不會被調用。
當咱們的手指按下黑色區域,停留幾秒再擡起,獲得的Log以下圖:
能夠看出,第一個事件的類型爲action down,最後一個爲action up,中間的都是action move的類型,這正好符合上一篇文章介紹的Android的手勢定義。
二、MyLayout的onInterceptTouchEvent返回false,MyView的onTouchEvent返回false
改寫MyView中onTouchEvent的代碼,令其返回false
[java] view plaincopy
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent.");
LogUtil.logAction(event, TAG);
return false;
}
因爲MyView沒有消耗touch事件,MyLayout的onTouchEvent將會被調用,打印的log以下:
能夠看出,touch的類型只爲action down。
三、MyLayout的onInterceptTouchEvent返回true
改寫MyLayout中的onInterceptTouchEvent代碼,令其返回true
[java] view plaincopy
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent");
return true;
}
因爲MyLayout攔截了touch事件,MyView中的onTouchEvent將不會被調用,log以下:
以上對Android的onInterceptTouchEvent和onTouchEvent的描述如有不妥之處,歡迎指正。
本文參考的代碼出自:兩分鐘完全讓你明白Android中onInterceptTouchEvent與onTouchEvent(圖文)!,感謝做者的無私分享。