经过了一段Android的学习,基本上了解了Android的基础知识。今天,我们来研究一下Android中特有的手势识别技术,即Gesture。首先,我从网上找了很多资料,具体归纳起来有2类:一类是触摸屏手势识别,另一类是输入法手势识别。

我们先来讨论一下第一类触摸屏手势识别,这个比较简单,就是利用触摸屏的Fling、Scroll等Gesture(手势)来操作屏幕,比如用Scroll手势在 浏览器中滚屏,用Fling在阅读器中翻页等。在Android系统中,手势的识别是通过 GestureDetector.OnGestureListener接口来实现的。下面通过我自己的一个动手实验来进行介绍。

首先,我们在Eclipse中创建一个工程,名称叫SignFilpDemo。然后,在src中创建一个SignFilpDemo源文件。这个工程是基于Android1.6的。因为,在Android 1.6之前的版本中,需要开发者编写大量的代码才能实现某些更为复杂的Gestures功能。而在之后的版本SDk中嵌入标准的Gestures API库(Package: android.gesture),包括了所有与Gesture技术相关的操作:存储、加载、创建新Gestures和识别等。其工程结构如下:



图1

接着,我们知道Android的事件处理机制是基于Listener(监听器)来实现的,比如我们今天所说的触摸屏相关的事件,就是通过onTouchListener。因此,我们在源代码中要实现这个接口。另外,我们还要实现OnGestureListener接口,因为,那个手势的识别是通过 GestureDetector.OnGestureListener接口来实现的。其中,onTouchEvent方法则是实现了OnTouchListener中的抽象方法,我们只要在这里添加逻辑代码即 可在用户触摸屏幕时做出响应。在这里我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给 GestureDetector 来分析是否有合适的callback函数来处理用户的手势。接下来,就是实现了以下6个抽象方法,其中最有用的当然是onFling()、onScroll()和onLongPress()了。下面介绍一下:

(1) 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发,其源代码如下:

public boolean onDown(MotionEvent e) {

return false;

}

public void onShowPress(MotionEvent e) {

}

(2) 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发,其源代码如下:

public boolean onSingleTapUp(MotionEvent e) {

return false;

}

(3) 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发

// 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发

public void onLongPress(MotionEvent e) {

}

// 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY) {

return false;

}

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {

return false;

}

我们今天来做一个onFling()事件的处理吧,这里需要注意的是Fling事件的处理代 码中,除了第一个触发Fling的ACTION_DOWN和最后一个ACTION_MOVE中包含的坐标等信息外,我们还可以根据用户在X轴或者Y轴上的 移动速度作为条件。在这个例子中,我们是根据用户在屏幕上移动的x轴坐标或者是y轴坐标位移来判断方向。如果x轴坐标位移大于50向左,小于-50向右,如果y轴坐标位移大于50向上,小于-50向下。源代码如下:

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,

float velocityY) {

if (e1.getX() - e2.getX() > 50) {

Toast.makeText(SignFlipDemo.this, "左", Toast.LENGTH_LONG).show();

return true;

} else if (e1.getX() - e2.getX() < -50) {

Toast.makeText(SignFlipDemo.this, "右", Toast.LENGTH_LONG).show();

return true;

} else if (e1.getY() - e2.getY() > 50) {

Toast.makeText(SignFlipDemo.this, "上", Toast.LENGTH_LONG).show();

return true;

} else if (e1.getY() - e2.getY() < -50) {

Toast.makeText(SignFlipDemo.this, "下", Toast.LENGTH_LONG).show();

return true;

}

return false;

}

如果鼠标向上移动,运行效果如下图2所示:



图2

如果鼠标向下移动,运行效果如下图3所示:



图3

如果鼠标向左移动,运行效果如下图4所示:



图4

如果鼠标向右移动,运行效果如下图5所示:



图5

通过上面的运行结果可以看出,只要鼠标向上下左右四个方向移动,就是相应地识别出,并且显示出相应的方向。这里需要注意的是因为是模拟器,所以只有通过鼠标来模拟,在真机环境中,就是触摸屏的识别了。

接下来,我们来讨论一下第二种输入法手势识别。这种方法就是需要定义一个描述手势动作的文件。在手写输入中,会为每一个字符定义一个特征码,这些特征码都保存在相应的文件中(可能有一个或多个这样的文件),当用户绘制一个描述字符的图形时,系统会为所绘制的图形提取特征码,然后会在保存特征码文件中查找相对应的特征码,如果找到,就会将对应的字符返回。其中,这些文件被称为手势文件。这里我们讨论的是在Android 2.1中提供了一个GestureBuilder工程(实际上从Android 1.6就带这个例子了),这个工程是一个手势API的演示,主要功能是建立手势信息,并将手势信息保存在手势文件中。下面,我们来演示一下。

首先在Eclipse中打开这个工程,然后可以直接导入运行。运行后界面如图6所示。



图6

由于上面还没建立手势,所以手势列表为空。下面开始建立我们的第一个手势。单击“Add gesture”按钮,会进入建立手势的界面。如图7所示。建立手势需要两个信息:手势名和手势图形。在文本框中输入任意的字符串,如“矩形”,并且在文本框下面画一个如图7所示的矩形(差不多就行,不一定要很标准)。然后单击“Done”按钮,第一个手势已经建立成功了。按着这种方法,再建立几个手势。每成功建立完一个手势后,会在主界面的列表中看到我们所建立的手势,如图8所示。进入DDMS透视图,会在SD卡的根目录看到一个gestures文件,如图9所示。然后将该文件导出到PC上,以备以后使用。



图7




图8






图9

通过前面的介绍,我们知道绘制手势图像好像是在一个类似画布的区域,实际上,这是一个android.gesture.GestureOverlayView组件。我们可以在这个组件上绘制手势,并会触发一个识别手势的事件。了解了原理,接下来,我们利用手势自动输入字符串。

首先需要在布局文件中添加一个EditText和GestureOverlayView组件,代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<EditText android:id="@+id/edittext"

android:layout_height="wrap_content" android:layout_width="fill_parent"/>

<android.gesture.GestureOverlayView

android:gestureStrokeType="multiple" android:id="@+id/gestures"

android:layout_height="fill_parent" android:layout_width="fill_parent"/>

</LinearLayout>

接着,使用手势文件的第一步是装载手势文件。可以将手势文件放在SD卡的相应目录,也可以放在apk中一起打包。在本例中将gestures文件放在了工程目录的res\raw目录中,因此,这个手势文件是包含在apk文件中的。下面在onCreate方法中装载这个手势文件,代码如下:

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

edittext = (EditText)findViewById(R.id.edittext);

// 从res\raw目录中装载gestures文件

gestureLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);

// 如果成功装载手势文件,获得GestureOverlayView对象,并向该对象注册事件

if(gestureLibrary.load())

{

setTitle("手势文件装载成功。");

GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestures);

gestures.addOnGesturePerformedListener((OnGesturePerformedListener) this);

}

else

{

setTitle("手势文件装载失败。");

}

}

处理手势识别事件需要实现GestureOverlayView.OnGesturePerformedListener接口,该接口有一个事件方法,当绘制完手势图形后被调用,可根据相应的API来判断是否成功识别了当前手势,该事件的代码如下:

public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture){

ArrayList predictions = gestureLibrary.recognize(gesture);

if(predictions.size()>0){

// predictions保存了所有与当前手势可能匹配的候选手势

for(int i=0;i<predictions.size();i++)

{

Prediction prediction = (Prediction) predictions.get(i);

if(prediction.score>1.0)

{

// 只选择了第一个与当前手势匹配的手势,将手势名输出的文本框中

edittext.append(prediction.name);

break;

}

}

}


}

运行效果如图10








图10

上面,我们已经实现了输入手势识别,绘制手势,程序自动输入对应的文本。主要是导入外部的手势文件进行识别。

本文主要介绍了Android中的两种手势识别技术。一类是触摸屏手势识别,另一类是输入法手势识别。相比较,第一种容易实现,第二种实现起来复杂,还要创建手势文件。在实验中,我碰到一个问题,那就是DDMS中没有显示sdcard文件,这耗费我很长时间,后来只能通过外面的DDMS工具导入gestrue文件。如果有知道的朋友告诉我一下,在此表示谢谢。其实,在第二种识别中,我们可以不用自带的GestureBuilder文件来创建手势文件,那个相对复杂一些,可以自己写一个工程来创建。这里篇幅有限,就留给读者自己思考了。



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/tsdl2009/archive/2010/08/13/5810922.aspx

更多相关文章

  1. 转载:Android的设置界面及Preference使用
  2. Android中的控件
  3. 安卓系统结构
  4. android中javah生成jni头文件报错问题
  5. Android(安卓)反编译apk 到java源码的方法
  6. 双击运行Android模拟器、创建SDcard、AVD、安装APK文件、上传文
  7. 最全的Android项目结构以及功能
  8. Android(安卓)实现答题器功能(通过手势实现翻页效果)
  9. NPM 和webpack 的基础使用

随机推荐

  1. 互联网公司Android客户端面试 知识点
  2. 反编译介绍
  3. Android(安卓)检测网络连接状态
  4. Android(安卓)开发——'Android(安卓)Pre
  5. 【 Android】使手机屏幕常亮,不进入待机状
  6. 最好的Android(安卓)apps,Android(安卓)a
  7. android使用http协议上传文件
  8. Android(安卓)Java 线程池 ScheduledThre
  9. 2.高焕堂讲解 ContentProvider范例
  10. android的Intent