Android移动开发-添加手势以及识别用户手势
所谓手势,其实是指用户手指或触摸笔在触摸屏上的连续触碰的行为,比如在屏幕上从左向右划出的一个动作,就是手势;再比如在屏幕上画出一个圆圈也是手势。手势这种连续的触碰会形成某个方向上的移动趋势,也会形成一个不规则的几何图形。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" />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里添加的权限代码如下:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <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 { 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 predictions = gestureLibrary.recognize(gesture); //① ArrayList result = new ArrayList(); // 遍历所有找到的Prediction对象 for (Prediction pred : predictions) { // 只有相似度大于2.0的手势才会被输出 if (pred.score > 2.0) { result.add("与手势【" + pred.name + "】相似度为" + pred.score); } } if (result.size() > 0) { ArrayAdapter
注意:上面的程序同样需要将手势库保存在SD卡上,因此还需要在清单文件AndroidManifest.xml里面添加程序的读写SD卡的权限。
- 在清单文件AndroidManifest.xml里添加的权限代码如下:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
上面的MainActivity.java程序中的标序号为①的代码就负责调用前一个程序的手势库来识别用户刚输入的手势,用户只要在屏幕上绘制一个大致与之前相似的手势,即可提示的结果。
更多相关文章
- Android(安卓)“再按一次返回键退出程序”
- Android(安卓)修改应用程序字体
- 初识Android的界面UI
- Android移动view动画问题 关于view的位置移动了,但view里面绑定的
- Android(安卓)手势检测---GestureDetector
- 资深程序员多年代码实践总结:《和Android源代码一起工作》 | Andr
- flex兼容 iOS和Android样式兼容 【微信小程序】
- android studio :利用安卓真机USB调试安卓程序
- 适用于Android的最佳免费待办事项列表应用程序以及如何使自己成