Android手势识别详解

一、使用GestureDetector进行手势识别

手势交互过程(原理):

1、触屏一刹那,触发MotionEvent事件
2、被OnTouchListener监听,在onTouch()中获得MotionEvent对象
3、GestureDetector转发MotionEvent对象至OnGestureListener
4、OnGestureListener获得该对象,根据该对象封装的信息做出和适当的反馈

MotionEvent

1、用于封装手势、触摸笔、轨迹球等动作事件
2、内部封装用于记录横轴和纵轴坐标的属性X和Y

GestureDetector

识别各种手势

触摸屏:按下、移动、抬起等

重载onTouch或者设置OnTouchListener

OnTouchListener工作原理:

当接收到用户触摸消息时,将消息交给GestureDetector加工
通过设置监听器获得GestureDetector处理后的手势

OnTouchListener提供两个监听器:

OnGestureListener:处理单击类消息
OnDoubleTapListener:处理双击类消息
OnGestureListener:
1、手势交互的监听接口,其提供多个抽象方法
2、根据GestureDetector的手势识别结果调用相对应的方法
OnGestureListener接口:
单击:onDown(MotionEvent e)
抬起:onSingleTapUp(MotionEvent e)
短按:onShowPress(MotionEvent e)
长按:onLongPress(MotionEvent e)
滚动:onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
滑动:onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
OnDoubleTapListener接口:
双击:onDoubleTap(MotionEvent e)
双击按下和抬起各触发一次:onDoubleTapEvent(MotionEvent e)
单击确认:onSingleTapConfirmed(MotionEvent e),即很快的按下并抬起,但并不连续点击第二下

对于上面的两种接口,我们可以直接继承SimpleOnGestureListener,然后重载感兴趣的手势。

使用实例:

1、布局文件

<RelativeLayout 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" >

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/guide_image1" />

</RelativeLayout>
2、实现手势识别
package com.cx.gesturedetectordemo;

import android.app.Activity;
import android.os.Bundle;
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.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {
	private ImageView image;
	private GestureDetector myGestureDetector;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		image = (ImageView) findViewById(R.id.image);
		
		//实例化GestureDetector
		myGestureDetector = new GestureDetector(this, new myOnGestureListener());
		
		//增加监听事件
		image.setOnTouchListener(new OnTouchListener() {
			
			@Override//可以捕获触摸屏幕发生的Event事件
			public boolean onTouch(View v, MotionEvent event) {
				//使用GestureDetector转发MotionEvent对象给OnGestureListener
				myGestureDetector.onTouchEvent(event);
				return true;
			}
		});
	}
	
	class myOnGestureListener extends SimpleOnGestureListener{
		
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			// TODO Auto-generated method stub
			if(e1.getX()-e2.getX()>50){
				Toast.makeText(MainActivity.this, "向左滑动", Toast.LENGTH_SHORT).show();
			}else if(e2.getX()-e1.getX()>50){
				Toast.makeText(MainActivity.this, "向右滑动", Toast.LENGTH_SHORT).show();
			}
			return super.onFling(e1, e2, velocityX, velocityY);
		}
	}

}

3、多个手指滑动识别。例如手机的UI界面,两个手指向内滑动→可操作界面,三个手指向内滑动→界面窗口视图。该内容为后来添加内容,下面源码中不包含该部分代码。

a.修改上面的ImageView的点击方法

image.setOnTouchListener(new OnTouchListener() {
	
	@Override//可以捕获触摸屏幕发生的Event事件
	public boolean onTouch(View v, MotionEvent event) {
		
		switch (event.getAction() & MotionEvent.ACTION_MASK) {  
		case MotionEvent.ACTION_DOWN:  
		    mode = 1;  
		    break;  
		case MotionEvent.ACTION_UP:  
		    mode = 0;  
		    break;  
		case MotionEvent.ACTION_POINTER_UP:  
		    mode -= 1;  
		    break;  
		case MotionEvent.ACTION_POINTER_DOWN:  
		    oldDist = spacing(event);//两点按下时的距离  
		    mode += 1;
		    break;        
		case MotionEvent.ACTION_MOVE:  
		    if (mode == 2) {  
		        float newDist = spacing(event);
		        //+-100是为了增加滑动幅度
		        if (newDist > oldDist+100) {  
		            Toast.makeText(MainActivity.this, "两指分!", Toast.LENGTH_SHORT).show();
		            //清零是为了防止多次执行
		            mode = 0;
		        }else if (newDist < oldDist-100) {  
		        	Toast.makeText(MainActivity.this, "两指聚!", Toast.LENGTH_SHORT).show();
		        	mode = 0;
		        }
		    }else if (mode == 3) {  
		        float newDist = spacing(event);  
		        if (newDist > oldDist+100) {  
		            Toast.makeText(MainActivity.this, "三指分!", Toast.LENGTH_SHORT).show();
		            mode = 0;
		        }else if (newDist < oldDist-100) {  
		        	Toast.makeText(MainActivity.this, "三指聚!", Toast.LENGTH_SHORT).show();
		        	mode = 0;
		        }
		    }
		    break;  
		}
		return true;
	}
});
b.增加计算移动距离的方法
private float spacing(MotionEvent event) {  
	float x = event.getX(0) - event.getX(1);  
	float y = event.getY(0) - event.getY(1);  
	return FloatMath.sqrt(x * x + y * y);  
}

二、使用GestureOverlayView进行手势识别

GestureOverlayView是一种用于手势输入的透明覆盖层,可覆盖在其他控件的上方,也可包含其他控件。存在3个监听器接口:

实现步骤:

1、使用Gestures Builder生成手势文件
2、加入项目
3、GestureOverlayView
拓展:笔画颜色、多笔画识别等、

监听器

GestureOverlayView.OnGestureListener 手势监听器
GestureOverlayView.OnGesturePerformedListener 手势执行监听器
GestureOverlayView.OnGesturingListener 手势执行中监听器

常见XML属性:

android:eventsInterceptionEnabled 定义当手势已经被识别出来时,是否拦截该手势动作
android:fadeDuration 当用户画完手势效果淡出的时间(ms)
android:fadeEnabled 用户画完之后手势是否自动淡出
android:gestureColor 手势的颜色
android:gestureStrokeType 笔画的类型
android:gestureStrokeWidth 笔画的粗细
使用实例:

1、生成手势文件

我们可以直接使用官方Demo来进行手势文件的生成,Demo位置:E:\eclipse\adt-bundle-windows-x86-20130219\sdk\samples\android-10\GestureBuilder

a.Demo导入:

需要new一个已经存在的项目,步骤如下


b.运行导入的项目,在应用中添加手势并生成手势文件。(生成的手势文件一般在SD卡的根目录)

c.将生成的手势文件放在新建工程的res/raw文件夹下

2、布局文件,添加GestureOverlayView控件

<RelativeLayout 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.gesture.GestureOverlayView
        android:id="@+id/gestureOverlayView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
        
        <ImageView
	        android:id="@+id/imageView1"
	        android:layout_width="wrap_content"
	        android:layout_height="match_parent"
	        android:layout_centerHorizontal="true"
	        android:layout_centerVertical="true"
	        android:src="@drawable/guide_image1" />
    </android.gesture.GestureOverlayView>

</RelativeLayout>
2、实现手势识别

package com.cx.gestureoverlayviewdemo;

import java.util.ArrayList;

import android.app.Activity;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity {
	private GestureOverlayView gestureOverlayView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		gestureOverlayView = (GestureOverlayView) findViewById(R.id.gestureOverlayView1);
		
		//从资源中将手势库文件加载进来
		final GestureLibrary library = GestureLibraries.fromRawResource(this, R.raw.gestures);
		library.load();
		//增加手势执行监听器
		gestureOverlayView.addOnGesturePerformedListener(new OnGesturePerformedListener() {
			
			@Override
			public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
				//读出手势库中的内容  识别手势
				ArrayList<Prediction> myGesture = library.recognize(gesture);
				Prediction prediction = myGesture.get(0);
				
				//判断相似度0.0~10.0
				if(prediction.score > 5.0){
					//通过名字判断手势
					if(prediction.name.equals("yes")){
						Toast.makeText(MainActivity.this, "正确!", Toast.LENGTH_SHORT).show();
					}else if(prediction.name.equals("no")){
						Toast.makeText(MainActivity.this, "错误!", Toast.LENGTH_SHORT).show();
					}else if(prediction.name.equals("next")){
						Toast.makeText(MainActivity.this, "下一步!", Toast.LENGTH_SHORT).show();
					}else if(prediction.name.equals("back")){
						Toast.makeText(MainActivity.this, "上一步!", Toast.LENGTH_SHORT).show();
					}
				}else{
					Toast.makeText(MainActivity.this, "无法识别!", Toast.LENGTH_SHORT).show();
				}
			}
		});
	}
}
源码下载
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c小旭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值