android:onTouch()和onTouchEvent()的區別?看完這篇文章就知道瞭

 Android Touch Screen 與傳統Click Touch Screen不同,會有一些手勢(Gesture),例如Fling,Scroll等等。這些Gesture會使用戶體驗大大提升。

Android中的Gesture識別(detector)是通過GestureDetector.OnGestureListener接口實現的。

首先,Android事件處理機制是基於Listener實現的,比如觸摸屏相關的事件,就是通過onTouchListener實現;

其次,所有View的子類都可以通過setOnTouchListener()、setOnKeyListener()等方法來添加對某一類事件的Listener;

第三,Listener一般會以Interface的方式來提供,其中包含一個或多個abstract方法,我們需要實現這些方法來完成 onTouch()、onKey()等操作。這樣,程序便可以在特定的事件被dispatch到該view的時候,通過callback函數給予適當的響 應。

 

1. Touch Screen Click舉例

public   class  MyGesture  extends  Activity  implements  OnTouchListener

{       

public   void  onCreate(Bundle savedInstanceState)

 {           

super .onCreate(savedInstanceState);           

setContentView(R.layout.main);           

TextView tv = (TextView) findViewById(R.id.tv);          

 tv.setOnTouchListener( this );      

 }       

public   boolean  onTouch(View v, MotionEvent event)

 {           

Toast.makeText( this ,  "Touch Touch" , Toast.LENGTH_SHORT).show();           

return   false ;      

 } 

  } 

我們可以通過MotionEvent的getAction()方法來獲取Touch事件的類型,包括 ACTION_DOWN(按下觸摸屏), ACTION_MOVE(按下觸摸屏後移動受力點), ACTION_UP(松開觸摸屏)和ACTION_CANCEL(不會由用戶直接觸發)。借助對於用戶不同操作的判斷,結合getRawX()、 getRawY()、getX()和getY()等方法來獲取坐標後,我們可以實現諸如拖動某一個按鈕,拖動滾動條等功能。

 

2. 當我們捕捉到Touch操作的時候,如何識別出用戶的Gesture?這裡我們需要GestureDetector.OnGestureListener接口的幫助,代碼如下:

public   class  MyGesture  extends  Activity  implements  OnTouchListener, OnGestureListener

{       

private  GestureDetector mGestureDetector;       

public  MyGesture()

 {           

mGestureDetector =  new  GestureDetector( this );      

 }       

public   void  onCreate(Bundle savedInstanceState)

{           

super .onCreate(savedInstanceState);           

setContentView(R.layout.main);          

 TextView tv = (TextView) findViewById(R.id.tv);          

 tv.setOnTouchListener( this );          

 tv.setFocusable( true );           

tv.setClickable( true );           

tv.setLongClickable( true );           

mGestureDetector.setIsLongpressEnabled( true );       

}              

  /*       * 在onTouch()方法中,我們調用GestureDetector的onTouchEvent()方法,將捕捉到的MotionEvent交給GestureDetector        * 來分析是否有合適的callback函數來處理用戶的手勢        */         

public   boolean  onTouch(View v, MotionEvent event)

{          

  return  mGestureDetector.onTouchEvent(event);      

 }          

// 用戶輕觸觸摸屏,由1個MotionEvent ACTION_DOWN觸發       

public   boolean  onDown(MotionEvent arg0)

{           

Log.i( "MyGesture" ,  "onDown" );           

Toast.makeText( this ,  "onDown" , Toast.LENGTH_SHORT).show();           

return   true ;       

}               

/*       * 用戶輕觸觸摸屏,尚未松開或拖動,由一個1個MotionEvent ACTION_DOWN觸發        * 註意和onDown()的區別,強調的是沒有松開或者拖動的狀態        */       

public   void  onShowPress(MotionEvent e)

 {           

Log.i( "MyGesture" ,  "onShowPress" );           

Toast.makeText( this ,  "onShowPress" , Toast.LENGTH_SHORT).show();       

}               

// 用戶(輕觸觸摸屏後)松開,由一個1個MotionEvent ACTION_UP觸發       

public   boolean  onSingleTapUp(MotionEvent e)

{          

 Log.i( "MyGesture" ,  "onSingleTapUp" );           

Toast.makeText( this ,  "onSingleTapUp" , Toast.LENGTH_SHORT).show();           

return   true ;      

 }              

  // 用戶按下觸摸屏、快速移動後松開,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE, 1個ACTION_UP觸發       

public   boolean  onFling(MotionEvent e1, MotionEvent e2,  float  velocityX,  float  velocityY)

{           

Log.i( "MyGesture" ,  "onFling" );           

Toast.makeText( this ,  "onFling" , Toast.LENGTH_LONG).show();           

return   true ;       

}              

  // 用戶按下觸摸屏,並拖動,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE觸發       

public   boolean  onScroll(MotionEvent e1, MotionEvent e2,  float  distanceX,  float  distanceY)

{           

Log.i( "MyGesture" ,  "onScroll" );          

 Toast.makeText( this ,  "onScroll" , Toast.LENGTH_LONG).show();           

return   true ;      

 }              

  // 用戶長按觸摸屏,由多個MotionEvent ACTION_DOWN觸發       

public   void  onLongPress(MotionEvent e)

 {           

Log.i( "MyGesture" ,  "onLongPress" );           

Toast.makeText( this ,  "onLongPress" , Toast.LENGTH_LONG).show();      

 } 

  }

3. Fling事件的處理代碼:除瞭第一個觸發Fling的ACTION_DOWN和最後一個ACTION_MOVE中包含的坐標等信息外,我們還可以根據用 戶在X軸或者Y軸上的移動速度作為條件。比如下面的代碼中我們就在用戶移動超過100個像素,且X軸上每秒的移動速度大於200像素時才進行處理。

public   boolean  onFling(MotionEvent e1, MotionEvent e2,  float  velocityX,  float  velocityY)

 {      

// 參數解釋:       

// e1:第1個ACTION_DOWN MotionEvent      

// e2:最後一個ACTION_MOVE MotionEvent       

// velocityX:X軸上的移動速度,像素/秒      

// velocityY:Y軸上的移動速度,像素/秒          

// 觸發條件 :       

// X軸的坐標位移大於FLING_MIN_DISTANCE,且移動速度大於FLING_MIN_VELOCITY個像素/秒               

final   int  FLING_MIN_DISTANCE =  100 , FLING_MIN_VELOCITY =  200 ;       

if  (e1.getX() – e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY)

{           

// Fling left           

Log.i( "MyGesture" ,  "Fling left" );           

Toast.makeText( this ,  "Fling Left" , Toast.LENGTH_SHORT).show();       

}

else   if  (e2.getX() – e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY)

{           

// Fling right           

Log.i( "MyGesture" ,  "Fling right" );           

Toast.makeText( this ,  "Fling Right" , Toast.LENGTH_SHORT).show();       

}       

return   false ;  

這個例子中,tv.setLongClickable(true)是必須的,因為 隻有這樣,view才能夠處理不同於Tap(輕觸)的hold(即ACTION_MOVE,或者多個ACTION_DOWN),我們同樣可以通過layout定義中的android:longClickable來做到這一點。

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *