怎么理解一个手势,就是在屏幕上,手画一个符号就是一个手势,它代表了用户的一个意图,也就是用户希望程序做点什么,一般程序大多数是通过按钮,按钮上有对应的文字,这样进行人机交互,而手势也是很多地方会使用到,而常用的手势好像下拉刷新,用户希望列表内容下拉一下就有新的信息,双指缩放等等,一般这些手势都是跟对应的view绑定起来,而今天介绍的都是方法是可以不绑定view,直接在界面上画一个手势就可以人机交互.实现的代码可以在github上的Demo源码了解.
这篇手势研究会大概分三部分
1. 手势Gesture使用方式
2. 展示手势开发的步骤及代码实现
3. 分析Gesture的源码及原理
使用的方式
首先我们需要把用户需要使用到的手势提前记录下来,准备一些手势的样本,在app安装时随着资源文件或者下载等方式存储到用户的手机里,当用户在app画一个手势时,就去匹配手势样本,当时样本最吻合时,就知道用户的意图,采取执行对应的功能,这样就是个很好的人机交互的方式.
从上文使用方式,我们大概猜想到,我们需要一个东西,用来管理和读取我们已经存储的手势样本,我们还要需要这个东西可以设别用户的手势跟我们已经存储的手势进行匹配.还有,我们需一个东西在app的界面上记录用户的手势,没错,两个东西都存在,就是GestureLibrary和GestureOverlayView,这两个类就是手势开发里使用的主要两个类,通过这两个类,我们就可以实现手势开发的所有功能,是不是很简单.
总结一下:
1. 提前准备好手势样本,在安装时加入到资源文件或者安装后网络下载.
2. 需要使用手势的界面里使用GestureOverlayView记录用户的手势,
3. 使用GestureLibrary对象对用户的手势进行监听和匹配,找到用户手势的意图,执行对应的功能
步骤及代码实现
手势库的初始化
GestureLibrary gLib=GestureLibraries.fromFile(手势库文件);
gLib.load();
这个过程是读取已经存储手势样本文件,构造出GestureLibrary实例的过程,需要第一步实现.对用户手势的监听
GestureOverlayView.addOnGesturePerformedListener()
使用GestureLibrary对用户的手势进行匹配
recognize(Gesture gesture)
- 循环遍历返回的ArrayList对象,使用Prediction的score来匹配手势的相似度,
score越高代表越匹配.
Prediction.score()
这里就是手势开发的实现的全部内容,但是作为一个程序猿,需要知其然知其所以然,就要对源码进行解剖.
原理
手势的结构
手势是用户在屏幕上画的符号,那么手势可以简单的一笔笔画,例如一个方向的箭头(>),也可以多笔划,很复杂,例如一个文字.这些都手势,所以我们就知道
手势是由一个或者多个笔画组成
学过数学的我们都到线是由点组成的,所以
一个手势笔画是由多个时间连续的点组成
一个点意味着什么呢,它会固定在屏幕的某个地方,还需要时间连续不断,所以
手势中的点包含坐标X轴和Y轴,还有时间戳
所以我们就很容易了解手势对应的文件了
GesturePoint : 是手势笔划中的一个点,包含X轴,Y轴的坐标,还有时间戳.
GestureStroke : 手势笔划,可以理解为线,由多个点组成的.
Gesture : 手势,代表用户的一个手势,可以由一个或者多个手势笔划组成.
GestureStore 手势仓库,里面存储了多个手势样本
手势的使用
使用手势的过程都是先从GestureLibrary开始,那么看看GestureLibrary的关系图.
从图中看,GestureLibrary的实现有两种,一个File的实现,另外一个是由资源Resource实现,说明我们的手势库可有两个方向可以构造.
然后看回GestureLibrary的源码
public abstract class GestureLibrary {
protected final GestureStore mStore;
...
}
里面只有一个对象,而所有的方法都是由这个对象实现,也就是GestureLibrary其实是GestureStore的代理类,而真正的功能其实是在GestureStore里.
GestureStore的内容很多,首先看到的是顶部注释里有手势文件的结构内容
Nb.bytes | Java type | Description |
---|---|---|
Header | ||
2 bytes | short | |
4 bytes | int | |
Entry | ||
X bytes | UTF String | |
4 bytes | int | |
Gesture | ||
8 bytes | long | |
4 bytes | int | |
Stroke | ||
4 bytes | int | |
Point | ||
4 bytes | float | |
4 bytes | float | |
8 bytes | long |
从源码可以知道,GestureStore的文件格式主要组成部分,也就是GestureLibrary读取文件的格式内容,也可以考虑根据这样的格式来进行加密,假如用手势来做成一个手写输入法的软件,那么手势库一定是庞大的内容库,而且根据所有人不同的手写方式,这样的手势库一定很有价值,至于怎样加密来保护这些价值,就可以考虑每个手势的内容进行拆分来分别存储和采取不同的加密方式加密.
然后我们再看Store对手势的读取保存
读取和保存
读取第一步GestureLibraries中读取手势文件
public boolean load() {
...
mStore.load(new FileInputStream(file), true);
...
}
第二步store获取文件流
public void load(InputStream stream, boolean closeStream) throws IOException {
DataInputStream in = null;
try {
in = new DataInputStream((stream instanceof BufferedInputStream) ? stream :
new BufferedInputStream(stream, GestureConstants.IO_BUFFER_SIZE));
...