Android Touch系統簡介(二):實例詳解onInterceptTouchEvent與onT

上一篇文章主要講述了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 plaincopy在CODE上查看代碼片派生到個人代碼片android

  1. public class MyView extends Button {  ide

  2.     private static final String TAG = MyView.class.getName();  函數

  3.   

  4.     public MyView(Context context){  佈局

  5.         super(context);  spa

  6.     }  .net

  7.   

  8.     public MyView(Context context, AttributeSet attrs) {  code

  9.         super(context, attrs);  orm

  10.     }  

  11.   

  12.     @Override  

  13.     public boolean onTouchEvent(MotionEvent event) {  

  14.         Log.d(TAG, "onTouchEvent.");  

  15.         LogUtil.logAction(event, TAG);  

  16.         return super.onTouchEvent(event);  

  17.     }  

  18. }  


建立類MyLayout,繼承自ViewGroup

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public class MyLayout extends FrameLayout{  

  2.     private static final String TAG = MyLayout.class.getName();  

  3.   

  4.     public MyLayout(Context context) {  

  5.         super(context);  

  6.     }  

  7.   

  8.     public MyLayout(Context context, AttributeSet attributeSet) {  

  9.         super(context, attributeSet);  

  10.     }  

  11.   

  12.     @Override  

  13.     public boolean onInterceptTouchEvent(MotionEvent ev) {  

  14.         Log.d(TAG, "onInterceptTouchEvent");  

  15.   

  16.         return super.onInterceptTouchEvent(ev);  

  17.     }  

  18.   

  19.     @Override  

  20.     public boolean onTouchEvent(MotionEvent event) {  

  21.         Log.d(TAG, "onTouchEvent.");  

  22.         LogUtil.logAction(event, TAG);  

  23.         return super.onTouchEvent(event);  

  24.     }  

  25. }  

LogUtil.logAction()函數是用來打印MotionEvent的動做類型,代碼以下:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public class LogUtil {  

  2.     public static void logAction(MotionEvent event, final String tag) {  

  3.         int action = event.getAction();  

  4.         switch(action) {  

  5.             case MotionEvent.ACTION_DOWN:  

  6.                 Log.d(tag, "action down");  

  7.                 break;  

  8.             case MotionEvent.ACTION_CANCEL:  

  9.                 Log.d(tag, "action cancel");  

  10.                 break;  

  11.             case MotionEvent.ACTION_UP:  

  12.                 Log.d(tag, "action up");  

  13.                 break;  

  14.             case MotionEvent.ACTION_MOVE:  

  15.                 Log.d(tag, "action move");  

  16.                 break;  

  17.             default:  

  18.                 Log.d(tag, "unknow action");  

  19.         }  

  20.     }  

  21. }  


佈局文件main.xml將MyView嵌套在MyLayout中,代碼以下:

[html] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. <view android:layout_width="fill_parent"  

  2.       android:layout_height="fill_parent"  

  3.       class="com.example.AndroidTest.MyLayout" xmlns:android="http://schemas.android.com/apk/res/android"  

  4.       android:id="@+id/view">  

  5.     <com.example.AndroidTest.MyView  

  6.             android:layout_width="fill_parent"  

  7.             android:layout_height="wrap_content"  

  8.             android:text="hello" />  

  9.       

  10. </view>  

MainActivity的代碼以下:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. public class MainActivity extends Activity {  

  2.     public static final String TAG = "TouchDemoActivity";  

  3.     @Override  

  4.     public void onCreate(Bundle savedInstanceState)  

  5.     {  

  6.         super.onCreate(savedInstanceState);  

  7.         setContentView(R.layout.main);  

  8.     }  

  9.   

  10. }  


程序啓動後,截圖以下。

下面分狀況討論程序的運行結果。

一、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在CODE上查看代碼片派生到個人代碼片

  1. @Override  

  2. public boolean onTouchEvent(MotionEvent event) {  

  3.     Log.d(TAG, "onTouchEvent.");  

  4.     LogUtil.logAction(event, TAG);  

  5.     return false;  

  6. }  


因爲MyView沒有消耗touch事件,MyLayout的onTouchEvent將會被調用,打印的log以下:

能夠看出,touch的類型只爲action down。


三、MyLayout的onInterceptTouchEvent返回true

改寫MyLayout中的onInterceptTouchEvent代碼,令其返回true

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

  1. @Override  

  2. public boolean onInterceptTouchEvent(MotionEvent ev) {  

  3.     Log.d(TAG, "onInterceptTouchEvent");  

  4.   

  5.     return true;  

  6. }  

因爲MyLayout攔截了touch事件,MyView中的onTouchEvent將不會被調用,log以下:



以上對Android的onInterceptTouchEvent和onTouchEvent的描述如有不妥之處,歡迎指正。

本文參考的代碼出自:兩分鐘完全讓你明白Android中onInterceptTouchEvent與onTouchEvent(圖文)!,感謝做者的無私分享。

相關文章
相關標籤/搜索