Android 手勢(Gesture)

1、什麼是手勢?ide

所謂手勢,其實就是指用戶手指或觸摸筆在觸摸屏上的連續觸碰行爲,好比在屏幕上蔥左至右劃出一個動做,就是手勢,再好比在屏幕上畫一個圓圈也是一個手勢,手勢這種連續的觸碰會造成某個方向上的移動趨勢,也會造成一個不規則的幾何圖形。Android對兩種手勢行爲都提供了支持:工具

一、對於第一種手勢行爲而言,Android提供了手勢檢測,併爲手勢檢測提供了相應的監聽器。this

二、對於第二種手勢行爲,Android容許開發者添加手勢,並提供了相應的API識別用戶手勢spa


2、手勢檢測code

Android爲手勢檢測提供了一個GestureDetector類,GestureDetector實例表明了一個手勢檢測器,建立GestureDetector時須要傳入一個GestureDetector.OnGestureListener監聽器,負責對用戶的手勢行爲提供響應。orm

GestureListener包含的事件處理方法以下:對象

boolean onDown(MotionEvent e):當觸碰事件按下時觸發該方法。事件

boolean onFling(MotionEvent e1,MotionEvent e2,float velocityX,float velocityY):當用戶在觸摸屏上"拖過"時觸發該方法。其中velocityX,velocityY表明"拖過"動做在橫向、縱向上的速度。圖片

abstract void onLongPress(MotionEvent e):當用戶在屏幕上長按時出發該方法。
ip

boolean onScroll(MotionEvent e1,MotionEvent e2,float distanceX,float distanceY):當用戶在屏幕上"滾動"時觸發該方法。

void onShowPress(MotionEvent e):當用戶在觸摸屏上按下、而且還爲移動和鬆開時觸發該方法。

boolean onSingleTapUp(MotionEvent e):用戶在觸摸屏上的輕擊事件將會出發該方法

如下代碼演示了,在什麼條件下觸發什麼手勢,觸發順序

public class MainActivity extends Activity implements GestureDetector.OnGestureListener{

   private static final String TAG="TAG";
   private
GestureDetector detector;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_main);
       
detector = new GestureDetector(this,this);
   
}

   /**
    * 添加手勢
    *
@param event
   
* @return
   
*/
   
@Override
   
public boolean onTouchEvent(MotionEvent event) {
       return detector.onTouchEvent(event);
   
}

   /**
    * 按下時
    *
@param e
   
* @return
   
*/
   
@Override
   
public boolean onDown(MotionEvent e) {
       Log.i(TAG,"detector onDown");
       return false;
   
}
   /**
    * 按下未移動時
    *
@param e
   
*/
   
@Override
   
public void onShowPress(MotionEvent e) {
       Log.i(TAG,"detector onShowPress");
   
}
   /**
    * 輕擊事件
    *
@param e
   
* @return
   
*/
   
@Override
   
public boolean onSingleTapUp(MotionEvent e) {
       Log.i(TAG,"detector onSingleTapUp");
       return false;
   
}
   /**
    * 滾動時
    *
@param e1
   
* @param e2
   
* @param distanceX
   
* @param distanceY
   
* @return
   
*/
   
@Override
   
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
       Log.i(TAG,"detector onScroll");
       return false;
   
}
   /**
    * 長按時
    *
@param e
   
*/
   
@Override
   
public void onLongPress(MotionEvent e) {
       Log.i(TAG,"detector onLongPress");
   
}
   /**
    * 快速滑動時
    *
@param e1
   
* @param e2
   
* @param velocityX
   
* @param velocityY
   
* @return
   
*/
   
@Override
   
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
       Log.i(TAG,"detector onFling");
       return false;
   
}
}

下面是經過Fling方法進行的一個滑動監聽仿的相似ViewPager

public class MainActivity3 extends Activity implements GestureDetector.OnGestureListener{

   private static final String TAG="TAG";
   private
GestureDetector detector;
   private
ViewFlipper mFlipper;
   private
Animation[] animations = new Animation[4];

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_gesture);
       
detector = new GestureDetector(this,this);
       
mFlipper = (ViewFlipper) findViewById(R.id.flipper);
       
mFlipper.addView(addImageView(R.mipmap.image));
       
mFlipper.addView(addImageView(R.mipmap.image2));
       
mFlipper.addView(addImageView(R.mipmap.image3));
       
mFlipper.addView(addImageView(R.mipmap.image4));

       
animations[0] = AnimationUtils.loadAnimation(this,R.anim.left_in);
       
animations[1] = AnimationUtils.loadAnimation(this,R.anim.left_out);
       
animations[2] = AnimationUtils.loadAnimation(this,R.anim.right_in);
       
animations[3] = AnimationUtils.loadAnimation(this,R.anim.right_out);
   
}

   private ImageView addImageView(int resId){
       ImageView imageView = new ImageView(this);
       
imageView.setImageResource(resId);
       
imageView.setScaleType(ImageView.ScaleType.CENTER);
       return
imageView;
   
}

   /**
    * 添加手勢
    *
@param event
   
* @return
   
*/
   
@Override
   
public boolean onTouchEvent(MotionEvent event) {
       return detector.onTouchEvent(event);
   
}

   /**
    * 按下時
    *
@param e
   
* @return
   
*/
   
@Override
   
public boolean onDown(MotionEvent e) {
       Log.i(TAG,"detector onDown");
       return false;
   
}
   /**
    * 按下未移動時
    *
@param e
   
*/
   
@Override
   
public void onShowPress(MotionEvent e) {
       Log.i(TAG,"detector onShowPress");
   
}
   /**
    * 輕擊事件
    *
@param e
   
* @return
   
*/
   
@Override
   
public boolean onSingleTapUp(MotionEvent e) {
       Log.i(TAG,"detector onSingleTapUp");
       return false;
   
}
   /**
    * 滾動時
    *
@param e1
   
* @param e2
   
* @param distanceX
   
* @param distanceY
   
* @return
   
*/
   
@Override
   
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
       Log.i(TAG,"detector onScroll");
       return false;
   
}
   /**
    * 長按時
    *
@param e
   
*/
   
@Override
   
public void onLongPress(MotionEvent e) {
       Log.i(TAG,"detector onLongPress");
   
}


   private final int FLIP_DISTANCE = 50;
   
/**
    * 快速滑動時
    *
@param e1
   
* @param e2
   
* @param velocityX
   
* @param velocityY
   
* @return
   
*/
   
@Override
   
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
       Log.i(TAG, "detector onFling");

       if
(e1.getX()-e2.getX()>FLIP_DISTANCE){
           mFlipper.setInAnimation(animations[2]);
           
mFlipper.setOutAnimation(animations[1]);
           
mFlipper.showNext();
           return true;
       
}else if(e2.getX()-e1.getX()>FLIP_DISTANCE){
           mFlipper.setInAnimation(animations[0]);
           
mFlipper.setOutAnimation(animations[3]);
           
mFlipper.showPrevious();
           return true;
       
}
       return false;
   
}

3、手勢識別庫

Android 手勢除了提供手勢檢測以外,還容許應用程序吧用戶手勢(多個持續的觸摸事件在屏幕種造成特定的形狀)添加到指定文件夾中,以備之後使用——若是程序須要,當用戶下次畫出該手勢時,系統可識別該手勢。

Android使用GestureLibrary來表明手勢哭,並提供了GestureLibraries工具類來建立手勢庫,GestureLibraries提供了以下4個靜態方法從不一樣位置加載手勢庫。

static GestureLibrary fromFile(String path):

static GestureLibrary fromFile(File path):

static GestureLibrary fromPrivateResource(Context context,int resourceID):從資源庫中加載手勢

當用戶獲取GestureLibrary 對象以後,該對象提供來以下方法來添加手勢、識別手勢。

void addGesture(String entryName,Gesture gesture):添加一個名爲entryName的手勢。

Set<String> getGestrueEntries():獲取該手勢哭腫的全部手勢名稱。

ArrayList<Gesture> getGestures(String entryName):獲取entryName名稱對應的所有手勢。

ArrayList<Prediction> recognize(Gesture gesture):從當前手勢庫中識別與gesture匹配的所有手勢。

————Prediction:name屬性表示匹配手勢名

————Prediction:score屬性表示了手勢類似度

void removeEntry(String entryName):刪除手勢庫中識別的entryName對應的手勢

void removeGesture(String entryName,Gesture gestrue):刪除手勢庫中entryName、gesture對應的手勢

boolean save():當手勢庫中添加手勢或從刪除手勢後調用改方法來保存手勢庫


手勢繪製與比對

Android 提供了一個手勢編輯組件:GestureOverlayView,該組件就像一個"繪圖組件",只是用戶繪製的是手勢,不是圖形。

爲了監聽GestureOverlayView Android提供了OnGestureListener、OnGesturePerformedListener、OnGesturingListener三個監聽器,分別用於監聽手勢事件的開始、結束、完成、取消等事件,通常最經常使用可能是OnGesturePerformedListener,用於提供完成時響應


public class MainActivity4 extends Activity{

   private GestureOverlayView mOverlay;
   private
ImageView mShowGesture;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       
setContentView(R.layout.activity_gesture2);
       
//獲取繪製手勢組件
       
mOverlay = (GestureOverlayView) findViewById(R.id.gesture_overlay);
       
//獲取繪製後顯示組件
       
mShowGesture = (ImageView) findViewById(R.id.show_gesture);

       
//添加繪製後監聽
       
mOverlay.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
           @Override
           
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {

               //將手勢轉換爲圖片
               
Bitmap bitmap = gesture.toBitmap(128, 128, 10, 0xffff0000);
               
mShowGesture.setImageBitmap(bitmap);

               
//獲取手勢庫
               
GestureLibrary gestureLibrary = GestureLibraries.fromFile("/mnt/sdcard/gestures");
               
//判斷手勢庫是否加載
               
if (gestureLibrary.load()) {
                   Toast.makeText(MainActivity4.this, "手勢文件已經裝載", Toast.LENGTH_SHORT).show();
               
}else{
                   Toast.makeText(MainActivity4.this, "手勢文件裝載失敗", Toast.LENGTH_SHORT).show();
               
}
               //獲取全部類似的手勢
               
ArrayList<Prediction> recognizes = gestureLibrary.recognize(gesture);
               
Toast.makeText(MainActivity4.this, "手勢數量:" + recognizes.size(), Toast.LENGTH_SHORT).show();
               
//遍歷類似的手勢,類似度高於5的纔打印
               
for (Prediction recognize : recognizes) {
                   if (recognize.score > 5.0) {
                       Toast.makeText(MainActivity4.this, "手勢名稱:" + recognize.name + " 類似度:" + recognize.score, Toast.LENGTH_SHORT).show();
                   
}
               }
               //添加手勢 (手勢名稱,手勢)
               
gestureLibrary.addGesture("gesture", gesture);
               
//保存手勢
               
gestureLibrary.save();
           
}
       });    }}
相關文章
相關標籤/搜索