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();
}
}); }}