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 实现手势添加


  1. 创建一个 空的 Android 项目 cn.twle.android.AddGesture

  2. 修改 activity_main.xml 添加一个 TextViewGestureOverlayView

    <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>
    
  3. 然后在 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>
    
  4. 修改 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();
                }
            });
        }
    }
    
  5. 最后在 AndroidManifest.xml 文件中加入读 SD 卡的权限

        </application>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    </manifest>
    

手势识别

我们再写一个 demo 实现手势识别

  1. 复用上面的 demo

  2. 修改 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();
                    }
                }
            });
        }
    }
    
  3. 然后在 AndroidManifest.xml 文件中加入读 SD 卡的权限

        </application>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    </manifest>
    

参考文档

  1. 官方 API 文档: GestureDetector

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.