Android Gesture 手势添加与识别
在上一章节我们讲了手势 (Gesture) 的基本知识和基本的手势检测,其实,Android 还允许我们将手势进行保存,然后提供了相关的识别 API
GestureLibrary
Android 提供了 GestureLibrary
代表手势库,提供了 GestureLibraries 工具类来创建手势
android.gesture.GestureLibraries 提供了四个加载手势库的静态方法
GestureLibrary fromFile(String path) GestureLibrary fromFile(File path) GestureLibrary fromPrivateFile(Context context, String name) GestureLibrary fromRawResource(Context context, int resourceId)
获得 GestureLibraries 对象后,就可以使用该对象提供的下述方法来做相应操作
方法 | 说明 |
---|---|
void addGesture(String entryName, Gesture gesture) | 添加一个名为 entryName 的手势 |
Set<String>getGestureEntries() | 获得手势库中所有手势的名称 |
ArrayList<Gesture> getGestures(String entryName) | 获得 entryName 名称对应的全部手势 |
ArrayList<Prediction>recognize (Gesture gesture) | 从当前手势库中识别与gesture匹配的全部手势 |
void removeEntry(String entryName) | 删除手势库中 entryName 名称对应的手势 |
void removeGesture(String entryName, Gesture gesture) | 删除手势库中 entryName 和 gesture 都匹配的手势 |
abstract boolean save() | 想手势库中添加手势或从中删除手势后调用该方法保存手势库 |
GestureOverlayView 手势编辑组件
Android 为 GestureOverlayView 提供了三种监听器接口
GestureOverlayView.OnGestureListener GestureOverlayView.OnGesturePerformedListener GestureOverlayView.OnGesturingListener
常用的是 OnGesturePerformedListener 用于手势完成时提供响应
范例: 手势添加
我们写一个 demo 实现手势添加
-
创建一个 空的 Android 项目
cn.twle.android.AddGesture
-
修改
activity_main.xml
添加一个TextView
和GestureOverlayView
<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=".MainActivity"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="请在下方屏幕中绘制手势~" android:textSize="20sp"/> <!-- gestureStrokeType 控制手势是否需要一笔完成,multiple 表示允许多笔 --> <android.gesture.GestureOverlayView android:id="@+id/gesture" android:layout_width="match_parent" android:layout_height="match_parent" android:gestureStrokeType="multiple" /> </LinearLayout>
-
然后在
res/layout
目录下新建dialog_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="8dp" android:text="输入手势名称"/> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/gesture_name"/> </LinearLayout> <ImageView android:id="@+id/gesture_show" android:layout_width="128dp" android:layout_height="128dp" android:layout_marginTop="10dp"/> </LinearLayout>
-
修改 MainActivity.java
package cn.twle.android.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 { private EditText editText; private GestureOverlayView gesture; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //获取手势编辑组件后,设置相关参数 gesture = (GestureOverlayView) findViewById(R.id.gesture); gesture.setGestureColor(Color.GREEN); gesture.setGestureStrokeWidth(5); gesture.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() { @Override public void onGesturePerformed(GestureOverlayView gestureOverlayView, final Gesture gesture) { View saveDialog = getLayoutInflater().inflate(R.layout.dialog_save,null,false); ImageView img_show = (ImageView) saveDialog.findViewById(R.id.gesture_show); final EditText edit_name = (EditText) saveDialog.findViewById(R.id.gesture_name); Bitmap bitmap = gesture.toBitmap(128,128,10,0xffff0000); img_show.setImageBitmap(bitmap); new AlertDialog.Builder(MainActivity.this).setView(saveDialog) .setPositiveButton("保存",new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { //获取文件对应的手势库 GestureLibrary gestureLib = GestureLibraries.fromFile("/mnt/sdcard/msgestures"); gestureLib.addGesture(edit_name.getText().toString(),gesture); gestureLib.save(); } }).setNegativeButton("取消", null).show(); } }); } }
-
最后在
AndroidManifest.xml
文件中加入读 SD 卡的权限</application> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> </manifest>
手势识别
我们再写一个 demo 实现手势识别
-
复用上面的 demo
-
修改
MainActivity.java
package cn.twle.android.addgesture; import android.content.Context; import android.gesture.Gesture; import android.gesture.GestureLibraries; import android.gesture.GestureLibrary; import android.gesture.GestureOverlayView; import android.gesture.Prediction; import android.graphics.Color; 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 { private GestureOverlayView gesture; private GestureLibrary gestureLibrary; private Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = MainActivity.this; gestureLibrary = GestureLibraries.fromFile("mmt/sdcard/msgestures"); if (gestureLibrary.load()) { Toast.makeText(mContext, "手势库加载成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(mContext, "手势库加载失败", Toast.LENGTH_SHORT).show(); } //获取手势编辑组件后,设置相关参数 gesture = (GestureOverlayView) findViewById(R.id.gesture); gesture.setGestureColor(Color.GREEN); gesture.setGestureStrokeWidth(5); gesture.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() { @Override public void onGesturePerformed(GestureOverlayView gestureOverlayView, final Gesture gesture) { //识别用户刚绘制的手势 ArrayList<Prediction> predictions = gestureLibrary.recognize(gesture); ArrayList<String> result = new ArrayList<String>(); //遍历所有找到的Prediction对象 for (Prediction pred : predictions) { if (pred.score > 2.0) { result.add("与手势【" + pred.name + "】相似度为" + pred.score); } } if (result.size() > 0) { ArrayAdapter<Object> adapter = new ArrayAdapter<Object>(mContext, android.R.layout.simple_dropdown_item_1line, result.toArray()); new AlertDialog.Builder(mContext).setAdapter(adapter,null).setPositiveButton("确定",null).show(); }else{ Toast.makeText(mContext,"无法找到匹配的手势!",Toast.LENGTH_SHORT).show(); } } }); } }
-
然后在
AndroidManifest.xml
文件中加入读 SD 卡的权限</application> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> </manifest>
参考文档
- 官方 API 文档: GestureDetector