您的位置:首页 > 移动开发 > Android开发

Android-----手势识别GestureDetector

2015-10-20 22:34 507 查看
手势操作原理
       首先,在Android系统中,每一次手势交互都会依照以下顺序执行。

       1. 接触接触屏一刹那,触发一个MotionEvent事件。

       2. 该事件被OnTouchListener监听,在其onTouch()方法里获得该MotionEvent对象。

       3. 通过GestureDetector(手势识别器)转发次MotionEvent对象至OnGestureListener。

       4. OnGestureListener获得该对象,听根据该对象封装的的信息,做出合适的反馈。

     

手势操作类和接口

       下面一同来了解一下MotionEvent、GestureDetector和OnGestureListener。

       MotionEvent: 这个类用于封装手势、触摸笔、轨迹球等等的动作事件。其内部封装了两个重要的属性X和Y,这两个属性分别用于记录横轴和纵轴的坐标。

       GestureDetector: 识别各种手势。

       OnGestureListener: 这是一个手势交互的监听接口,其中提供了多个抽象方法,并根据GestureDetector的手势识别结果调用相对应的方法。

手势操作各个方法的含义

       按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。

       抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。

       长按(onLongPress): 手指按在持续一段时间,并且没有松开。

       滚动(onScroll): 手指在触摸屏上滑动。

       按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效,在长按之前。

       抬起(onSingleTapUp):手指离开触摸屏的那一刹那。

任何手势动作都会先执行一次按下(onDown)动作。

       长按(onLongPress)动作前一定会执行一次按住(onShowPress)动作。

       按住(onShowPress)动作和按下(onDown)动作之后都会执行一次抬起(onSingleTapUp)动作。

       长按(onLongPress)、滚动(onScroll)和抛掷(onFling)动作之后都不会执行抬起(onSingleTapUp)动作。

通过GestureDetector.OnGestureListener来获取当前被触发的操作手势(Single Tap Up、Show Press、Long Press、Scroll、Down、Fling),具体包括以下几种:

boolean  onDoubleTap(MotionEvent e)

解释:双击的第二下Touch down时触发

boolean  onDoubleTapEvent(MotionEvent e)

解释:双击的第二下Touch down和up都会触发,可用e.getAction()区分。

boolean  onDown(MotionEvent e)

解释:Touch down时触发

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

解释:Touch了滑动一点距离后,up时触发。

void  onLongPress(MotionEvent e)

解释:Touch了不移动一直Touch down时触发

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

解释:Touch了滑动时触发。

void  onShowPress(MotionEvent e)

解释:Touch了还没有滑动时触发

(与onDown,onLongPress比较 onDown只要Touch down一定立刻触发。而Touchdown后过一会没有滑动先触发onShowPress再是onLongPress。

所以Touchdown后一直不滑动,onDown->onShowPress->onLongPress这个顺序触发。)

boolean  onSingleTapConfirmed(MotionEvent e)

boolean  onSingleTapUp(MotionEvent e)

解释:上面这两个函数都是在touch down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touchup时触发。

点击一下非常快的(不滑动)Touchup:

onDown->onSingleTapUp->onSingleTapConfirmed

点击一下稍微慢点的(不滑动)Touchup:

onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed

例子

package com.gjg.gesturedemo;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;

public class OtherActivity extends Activity implements OnTouchListener {

private Button mButton = null;
GestureDetector mGesture = null;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.other);

Log.i("TEST", "onCreate");
mButton = (Button) findViewById(R.id.button1);
mButton.setOnTouchListener(this);
mGesture = new GestureDetector(this, new GestureListener());
}

@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return mGesture.onTouchEvent(event);
}

class GestureListener extends SimpleOnGestureListener {

@Override
public boolean onDoubleTap(MotionEvent e) {
// TODO Auto-generated method stub
Log.i("TEST", "onDoubleTap");
return super.onDoubleTap(e);
}

@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
Log.i("TEST", "onDown");
return super.onDown(e);
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
Log.i("TEST", "onFling:velocityX = " + velocityX + " velocityY"
+ velocityY);
return super.onFling(e1, e2, velocityX, velocityY);
}

@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
Log.i("TEST", "onLongPress");
super.onLongPress(e);
}

@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
Log.i("TEST", "onShowPress");
super.onShowPress(e);
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// TODO Auto-generated method stub
Log.i("TEST", "onScroll:distanceX = " + distanceX + " distanceY = "
+ distanceY);
return super.onScroll(e1, e2, distanceX, distanceY);
}

@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
Log.i("TEST", "onSingleTapUp");
return super.onSingleTapUp(e);
}

}
}


按如下的动作执行:单击---->双击---->拖拽---->长按

logcat打印的信息如下:



手势识别的例子

导入系统自带的GestureBuilder,该项目在Android的sdk下的samples中,具体路径\Android\android-sdk\samples\android-8

添加对应的手势



在sdcard下生成gesture,将其copy到你的项目中的raw文件中



布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.gjg.gesturedemo.MainActivity" >

<android.gesture.GestureOverlayView
android:id="@+id/gesture"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#000000"
android:gestureStrokeType="multiple" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<Button
android:id="@+id/recoginze"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="recongize"
android:text="@string/recognize" />

</LinearLayout>

</LinearLayout>


注意:android.gesture.GestureOverlayView是系统自带的,包名要写全

          android:gestureStrokeType="multiple"  //   multiple多笔    single单笔

Java代码

实现的功能:

识别“v”,关闭当前的应用;

识别“c”,拨打指定的电话号码;

识别“x”,显示一条toast信息。

package com.gjg.gesturedemo;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGestureListener;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {
public static String Tag="MainActivity";
private GestureLibrary library;
private Gesture gesture;
private GestureOverlayView overlayView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//得到手势库
library=GestureLibraries.fromRawResource(this, R.raw.gestures);
//加载手势库
library.load();

overlayView =(GestureOverlayView) findViewById(R.id.gesture);
//适用于单笔手势
//overlayView.addOnGesturePerformedListener(new GesturePerformedListener());
//单笔和多笔都适用
overlayView.addOnGestureListener(new GestureListener());
}

public void recongize(View v){
recognizedGesture(gesture);
overlayView.clear(true);
}

private final class GestureListener implements OnGestureListener{

@Override
public void onGestureStarted(GestureOverlayView overlay,
MotionEvent event) {
Log.e(Tag, "onGestureStarted");

}

@Override
public void onGesture(GestureOverlayView overlay, MotionEvent event) {
Log.e(Tag, "onGesture");

}

@Override
public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
Log.e(Tag, "onGestureEnded");
//得到最后画完的手势
gesture=overlay.getGesture();

}

@Override
public void onGestureCancelled(GestureOverlayView overlay,
MotionEvent event) {
Log.e(Tag, "onGestureCancelled");

}

}

private final class GesturePerformedListener implements OnGesturePerformedListener{

@Override
public void onGesturePerformed(GestureOverlayView overlay,
Gesture gesture) {
recognizedGesture(gesture);

}

}
private void recognizedGesture(Gesture gesture) {
//得到手势集合,最匹配的放在集合的第一条
ArrayList<Prediction> predictions=library.recognize(gesture);
if(!predictions.isEmpty()){
//得到第一个匹配值
Prediction prediction=predictions.get(0);
//匹配值:0<val<=10  1:10%的相似度
if(prediction.score>=6){
if("callPhone".equals(prediction.name)){
Intent intent=new Intent(Intent.ACTION_CALL,Uri.parse("tel:13727150778"));
startActivity(intent);
}else if("closeActivity".equals(prediction.name)){
finish();
}else if("showMessage".equals(prediction.name)){
Toast.makeText(this, "hello world!", 1).show();
}
}else{
Toast.makeText(MainActivity.this, "匹配度太低", 1).show();
}
}else{
Toast.makeText(MainActivity.this, "不匹配", 1).show();
}
}

@Override
protected void onDestroy() {
super.onDestroy();
Process.killProcess(Process.myPid());
}

}


运行效果:



代码下载地址:http://download.csdn.net/detail/dangnianmingyue_gg/9198067
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息