手势操作原理

       首先,在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打印的信息如下:

基于android的视频识别 android 识别物体_GestureLibrary


手势识别的例子

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

添加对应的手势

基于android的视频识别 android 识别物体_Gesture_02

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

基于android的视频识别 android 识别物体_Gesture_03

布局文件:

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



运行效果:

基于android的视频识别 android 识别物体_Gesture_04