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

Android移动开发-添加手势以及识别用户手势

2017-09-20 10:15 357 查看
所谓手势,其实是指用户手指或触摸笔在触摸屏上的连续触碰的行为,比如在屏幕上从左向右划出的一个动作,就是手势;再比如在屏幕上画出一个圆圈也是手势。手势这种连续的触碰会形成某个方向上的移动趋势,也会形成一个不规则的几何图形。Android对两种手势行为都是提供了支持。

- 对于第一种手势行为,Android提供了手势检测,并为手势检测提供了相应的监听器;

- 对于第二种手势行为,Android允许开发者添加手势,并提供了相应的API识别用户手势。

添加手势

Android除了提供手势检测之外,还允许应用程序把用户手势(多个持续的触摸事件在屏幕上形成特定的形状)添加到指定文件中,已备以后使用——如果程序需要,当用户下次再次画出该手势时,系统将可识别该手势。

下面的应用程序在界面布局中使用了GestureOverlayView。

布局文件layout/activity_main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请在下面屏幕上绘制手势" />
<!-- 使用手势绘制组件 -->
<android.gesture.GestureOverlayView
android:id="@+id/gesture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gestureStrokeType="multiple" />
<
4000
;/LinearLayout>


由于GestureOverlayView并不是标准的视图组件,因此在界面布局中使用该组件时需要使用全限类名。

上面的程序使用GestureOverlayView组件时指定了一个android:gestureStrokeType参数,该参数控制手势是否需要多一笔完成。大部分时候,一个手势只要一笔就可以完成,此时可将该参数设为single。如果该手势需要多笔来完成,则将该参数设为multiple。

接下来程序将会为GestureOverlayView添加一个OnGesturePerformedListener监听器,当手势事件完成时,该监听器会打开一个对话框,让用户选择保存该手势。

MainActivity.java逻辑代码:

package com.fukaimei.addgesture;

import android.content.DialogInterface;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

EditText editText;
GestureOverlayView gestureView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取文本编辑框
editText = (EditText) findViewById(R.id.gesture_name);
// 获取手势编辑视图
gestureView = (GestureOverlayView) findViewById(R.id.gesture);
// 设置手势的绘制颜色
gestureView.setGestureColor(Color.RED);
// 设置手势的绘制宽度
gestureView.setGestureStrokeWidth(4);
// 为gesture的手势完成事件监听器
gestureView.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {  //①
@Override
public void onGesturePerformed(GestureOverlayView overlay, final Gesture gesture) {
// 加载sava.xml界面布局代表的视图
View saveDialog = getLayoutInflater().inflate(R.layout.save, null);
// 获取saveDialog里的show组件
ImageView imageView = (ImageView) saveDialog.findViewById(R.id.show);
// 获取saveDialog里的gesture_name组件
final EditText gestureName = (EditText) saveDialog.findViewById(R.id.gesture_name);
// 根据Gesture包含的手势创建一个位图
Bitmap bitmap = gesture.toBitmap(128, 128, 10, 0xffff0000);
imageView.setImageBitmap(bitmap);
// 使用对话框显示saveDialog组件
new AlertDialog.Builder(MainActivity.this).setView(saveDialog).setPositiveButton("保存",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 获取指定文件对应的手势库
GestureLibrary gestureLib = GestureLibraries.fromFile("/mnt/sdcard/mygestures");  //②
// 添加手势
gestureLib.addGesture(gestureName.getText().toString(), gesture);  //②
// 保存手势库
gestureLib.save();  //②
}
}).setNegativeButton("取消", null).show();
}
});

}
}


上面程序中标为序号①的代码为GestureOverlayView绑定OnGesturePerformedListener监听器,该监听器用于在手势完成时提供响应——它的响应就是打开一个对话框。该对话框的界面布局代码如下。

layout/save.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

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

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dip"
android:text="请填手势名" />
<!-- 定义一个文本框来让用户输入手势名 -->
<EditText
android:id="@+id/gesture_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- 定义一个图片框来显示手势 -->
<ImageView
android:id="@+id/show"
android:layout_width="128dp"
android:layout_height="128dp"
android:layout_marginTop="10dp" />
</LinearLayout>


AddGesture程序中的标为②序号的代码是在对话框中完成的,这段代码用于从SD卡的指定文件中加载手势库,并添加用户刚刚输入的手势。

注意:上面的程序需要将手势库保存在SD卡上,因此还需要在清单文件AndroidManifest.xml里面添加程序的读写SD卡的权限。

在清单文件AndroidManifest.xml里添加的权限代码如下:

<!-- 在SD卡中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 向SD卡写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


识别用户手势

前面已经提到,GestureLibrary提供了recognize(Gesture ges)方法来识别手势,该方法将会返回该手势库中所有与ges匹配的手势——两个手势的图形越相似,相似度越高。

recognize(Gesture ges)方法的返回值为ArrayList< Predicttion>,其中Prediction封装了手势的匹配信息,Prediction对象的name属性代表了匹配的手势名,score属性代表了手势的相似度。

下面的程序将会利用前一个程序所创建的手势库来识别手势。该程序的界面很简单,只是在界面中定义了一个GestureOverlayView组件,允许用户在该组件上输入手势。程序为该组件绑定了OnGesturePerformedListener监听器,该监听器检测到用户手势完成时,就会调用手势库来识别用户输入的手势。

layout/activity_main.xml界面代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 使用手势编辑组件 -->
<android.gesture.GestureOverlayView
android:id="@+id/gesture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gestureStrokeType="multiple" />
</LinearLayout>


layout/result.xml界面代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ListView
android:id="@+id/show"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>


MainActivity.java逻辑代码:

package com.fukaimei.recognisegesture;

import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.Prediction;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

// 定义手势编辑组件
GestureOverlayView gestureView;
// 记录手机上已有的手势库
GestureLibrary gestureLibrary;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 读取上一个程序所创建的手势库
gestureLibrary = GestureLibraries.fromFile("/mnt/sdcard/mygestures");
if (gestureLibrary.load()) {
Toast.makeText(this, "手势文件装载成功", Toast.LENGTH_SHORT).show();
} else {

a5d5
Toast.makeText(this, "手势文件装载失败", Toast.LENGTH_SHORT).show();
}
// 获取手势编辑组件
gestureView = (GestureOverlayView) findViewById(R.id.gesture);
// 为手势编辑组价绑定事件监听器
gestureView.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
@Override
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
// 识别用户刚刚所绘制的手势
ArrayList<Prediction> predictions = gestureLibrary.recognize(gesture);  //①
ArrayList<String> result = new ArrayList<String>();
// 遍历所有找到的Prediction对象
for (Prediction pred : predictions) {
// 只有相似度大于2.0的手势才会被输出
if (pred.score > 2.0) {
result.add("与手势【" + pred.name + "】相似度为" + pred.score);
}
}
if (result.size() > 0) {
ArrayAdapter<Object> adapter = new ArrayAdapter<Object>(MainActivity.this,
android.R.layout.simple_dropdown_item_1line, result.toArray());
// 使用一个带List的对话框来显示所有匹配的手势
new AlertDialog.Builder(MainActivity.this).setAdapter(adapter, null)
.setPositiveButton("确定", null).show();
} else {
Toast.makeText(MainActivity.this, "无法找到能匹配的手势", Toast.LENGTH_SHORT).show();
}
}
});
}
}


注意:上面的程序同样需要将手势库保存在SD卡上,因此还需要在清单文件AndroidManifest.xml里面添加程序的读写SD卡的权限。

在清单文件AndroidManifest.xml里添加的权限代码如下:

<!-- 在SD卡中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 向SD卡写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


上面的MainActivity.java程序中的标序号为①的代码就负责调用前一个程序的手势库来识别用户刚输入的手势,用户只要在屏幕上绘制一个大致与之前相似的手势,即可提示的结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: