Android 手势识别类 ( 三 ) GestureDetector 源码浅析
前言:上 篇介绍了提供手势绘制的视图平台GestureOverlayView,但是在视图平台上绘制出的手势,是需要存储以及在必要的利用时加载取出手势。所 以,用户绘制出的一个完整的手势是需要一定的代码机制来完成存储以及必要时加载取出的;那么,在源码中Gesture这个类就是用来描述完整的手势的。一 个Gesture就是用户手指在触摸屏上绘制形成的不规则几何图形(A gesture is a hand-drawn shape on a touch screen);
一. Gesture的组成
通过前篇文章<<Android手势源码浅析-----手势绘制(GestureOverlayView)>>的 介绍,我们知道,当我们在GestureOverlayView上绘制手势时,形成的不规则几何图形是由多数个点形成的,这些点都有其对应的在屏幕上的坐 标值和时间戳(event.getEventTime());那么,这些点是如何组成Gesture的呢?针对这个问题,通过对Android手势源码的 浅析来寻求答案;
下图总体上大概描述了Gesture的形成结构,如下:
从上图描述的类关系中,可以知道:
1. 触摸屏上的点首先是通过GesturePoint这个类来描述的,GesturePoint封装点的x,y轴值和时间戳。
2.
GesturePoint中封装的点的信息会在GestureStroke类中被拆解处理,点对应的x,y值被拆解存放在GestureStroke的
float类型数组成员points中,而点对应的时间戳则放在long类型成员数组timestamps中。
3. GestureStroke表示一个手势行程(用户手指点下屏幕到手势离开屏幕绘制出的轨迹就是一个手势行程)。一个完整的手势由一个或多个手势行程组成(单笔画或多笔画绘制手势)
4. Gesture由单个或多个GestureStroke组成,Gesture类中的mStrokeBuffer成员为ArrayList类型集合,存放的是GestureStroke;
二. Gesture的形成过程:
当我们在GestureOverlayView上绘制手势时,会调用GestureOverlayView的touchDown、touchMove、touchUp方法,然后将通过这个三个方法捕获到的形成手势的多数个点组成Gesture。如下代码:
- public class GestureOverlayView extends FrameLayout {
- ...
- private void touchDown(MotionEvent event) {
- ...
- mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
- ...
- }
- private Rect touchMove(MotionEvent event) {
- ...
- mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
- ...
- }
- private void touchUp(MotionEvent event, boolean cancel) {
- ...
- mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
- ...
- }
- ...
- }
---->通过上面的代码可知,当用户正在绘制手势时,会调用touchDown、touchMove,执行mStrokeBuffer.add(new
GesturePoint(x, y, event.getEventTime())),实现将点的x、y、event.getEventTime() 值作为GesturePoint的构造函数的实参创建GesturePoint对象,然后将得到的GesturePoint添加到mStrokeBuffer集合中(mStrokeBuffer为ArrayList<GesturePoint>类型);
GesturePoint的源代码如下:
- /*
- * Copyright (C) 2008-2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package android.gesture;
- import java.io.DataInputStream;
- import java.io.IOException;
- /**
- * A timed point of a gesture stroke. Multiple points form a stroke.
- */
- //一个手势行程的定时点,多个点形成一个手势行程。GesturePoint封装x,y轴和时间戳的值
- public class GesturePoint {
- public final float x;
- public final float y;
- public final long timestamp;
- public GesturePoint(float x, float y, long t) {
- this.x = x;
- this.y = y;
- timestamp = t;
- }
- //从输入流中读取之前保存在文件中的数据
- static GesturePoint deserialize(DataInputStream in) throws IOException {
- // Read X and Y
- final float x = in.readFloat(); //从输入流中读出对应x轴的坐标值 (来自通过调用GestureStroke的函数serialize保存的,下同)
- final float y = in.readFloat(); //从输入流中读出对应y轴的坐标值
- // Read timestamp
- final long timeStamp = in.readLong(); //从输入流中读出对应的时间戳
- return new GesturePoint(x, y, timeStamp);
- }
- @Override
- public Object clone() {
- return new GesturePoint(x, y, timestamp);
- }
- }
通过源码可知,在GesturePoint的构造函数中,将传进来的点的各个信息值分别赋值给自身的成员变量x、y、timestamp;所以GesturePoint描述的就是组成完成手势中的一个点元素;而GestureOverlayView中的mStrokeBuffer集合保存着组成手势的多数个点
---->紧接着,当用户完成手势绘制手指离开屏幕时,会调用touchUp,执行 mCurrentGesture.addStroke(new
GestureStroke(mStrokeBuffer)),实现将之前绘制手势得到的mStrokeBuffer集合作为GestureStroke构造函数的实参创建GestureStroke对象,然后将GestureStroke对象作为mCurrentGesture(Gesture对象)的方法addStroke的实参,实现将GestureStroke添加到Gesture中;
GesturePoint的部分源代码如下:
- /**
- * A gesture stroke started on a touch down and ended on a touch up. A stroke
- * consists of a sequence of timed points. One or multiple strokes form a gesture.
- */
- public class GestureStroke {
- ...
- public final float length; //length为手势行程的长度
- public final float[] points; //保存组成手势行程的多数个点的x,y坐标值
- private final long[] timestamps;//保存组成手势行程的多数个点的时间戳
- /**
- * A constructor that constructs a gesture stroke from a list of gesture points.
- *
- * @param points
- */
- public GestureStroke(ArrayList<GesturePoint> points) {
- final int count = points.size();
- final float[] tmpPoints = new float[count * 2];
- final long[] times = new long[count];
- RectF bx = null;
- float len = 0;
- int index = 0;
- for (int i = 0; i < count; i++) {
- final GesturePoint p = points.get(i);
- tmpPoints[i * 2] = p.x; //偶数位置保存x值
- tmpPoints[i * 2 + 1] = p.y; //奇数位置保存x值
- times[index] = p.timestamp;
- if (bx == null) {
- bx = new RectF();
- bx.top = p.y;
- bx.left = p.x;
- bx.right = p.x;
- bx.bottom = p.y;
- len = 0;
- } else {
- //Math.pow(a,b)为a的b次方,如Maht.pow(3,2)等于9。下面的公式相当于平方和的根号值
- len += Math.sqrt(Math.pow(p.x - tmpPoints[(i - 1) * 2], 2)
- + Math.pow(p.y - tmpPoints[(i -1 ) * 2 + 1], 2));
- //放大bx覆盖到指定的p.x, p.y点
- bx.union(p.x, p.y);
- }
- index++;
- }
- timestamps = times;
- this.points = tmpPoints;
- boundingBox = bx;
- length = len;
- }
- ...
- }
通过上面的代码可知,当我们创建GestureStroke的对象时,会执行GestureStroke的构造函数。而在GestureStroke的构造函数中,实现将传进来的mStrokeBuffer集合中封存的多个点进行遍历拆解出来,然后分别赋值给GestureStroke的数组成员变量points,timestamps,同时也根据点的坐标值计算出手势行程的长度length;
---->接着,将创建得到的GestureStroke对象通过调用Gesture的addStroke方法添加到Gesture类的mStrokes中,Gesture的addStroke方法源码实现如下:
- /**
- * A gesture is a hand-drawn shape on a touch screen. It can have one or multiple strokes.
- * Each stroke is a sequence of timed points. A user-defined gesture can be recognized by
- * a GestureLibrary.
- */
- /*手势时是触摸屏上手势绘制的形状,它可以单笔画或者多笔画,
- * 每一个笔画是一个计时点序列,用户绘制定义的手势可以通过GestureLibrary来识别
- */
- public class Gesture implements Parcelable {
- ...
- private final ArrayList<GestureStroke> mStrokes = new ArrayList<GestureStroke>();
- ...
- /**
- * Adds a stroke to the gesture.
- *
- * @param stroke
- */
- public void addStroke(GestureStroke stroke) {
- mStrokes.add(stroke);
- ...
- }
- ...
- ...
- }
所以,在Gesture的成员mStrokes中存放着是用户在触摸屏上绘制形成的当前手势相关信息。在Gesture中会根据得到的mStrokes
中这些信息去进行一些重要的处理,如将其序列化存储(serialize)、手势转化成bitmap显示(toBitmap)、还原手势的绘制路径
(toPath)等;
最后,针对手势组成类之间的关系进行一个小结:
1). GesturePoint: 描述用户手指在屏幕位置的一个定时点,封装用户手指在屏幕上的点坐标值以及时间戳,时间戳由event.getEventTime()决定。
2). GestureStroke:描述用户手指在屏幕上滑动到手指离开屏幕时所产生的轨迹线(由多个时间序列点形成),一个GestureStroke由多个GesturePoint组成。
3). Gesture:实现Parcelable接口,描述用户完成绘制的完整手势,一个Gesture由单个或多个GestureStroke组成。手势绘制可通过GestureOverlayView.setGestureStrokeType(inttype)来设置单笔和多笔画。
借鉴:http://blog.csdn.net/stevenhu_223/article/details/9529837
Android 手势识别类 ( 三 ) GestureDetector 源码浅析的更多相关文章
- Android 手势识别类 ( 二 ) GestureDetector 源码浅析
前言:Android 关于手势的操作提供两种形式:一种是针对用户手指在屏幕上划出的动作而进行移动的检测,这些手势的检测通过android提供的监听器来实现:另一种是用 户手指在屏幕上滑动而形成一定的不 ...
- 16 BasicHashTable基本哈希表类(三)——Live555源码阅读(一)基本组件类
这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...
- Android Handler机制(三)----Looper源码解析
一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...
- Android 手势识别类 ( 一 ) GestureDetector 基本介绍
为了加强鼠标响应事件,Android提供了GestureDetector手势识别类.通过GestureDetector.OnGestureListener来获取当前被触发的操作手势(Single Ta ...
- Android源码浅析(三)——Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机
Android源码浅析(三)--Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机 最近比较忙,而且又要维护自己的博客,视频和公众号,也就没 ...
- Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令
Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...
- Android开发之Theme、Style探索及源码浅析
1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...
- Android源码浅析(五)——关于定制系统,如何给你的Android应用系统签名
Android源码浅析(五)--关于定制系统,如何给你的Android应用系统签名 今天来点简单的我相信很多定制系统的同学都会有一些特定功能的需求,比如 修改系统时间 静默安装 执行某shell命令 ...
- Android源码浅析(二)——Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境
Android源码浅析(二)--Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境 接着上篇,上片主要是介绍了一些安装工具的小知识点Andr ...
随机推荐
- css复习笔记
margin: 1. 当有三个值时第一个值为上,第二个值为左右,第三个值为下. 2.margin外边距折叠,水平没有,垂直会折叠,且折叠后以两者最大值为准.另外,当一个元素包裹另一元素时也会发生折叠. ...
- SAP中给当前指定的活动用户发系统信息的函数
函数名:TH_POPUP 输入集团.当前在线用户.Message即可
- MapGIS转Shp文件的单位问题
在MapGIS浏览查看一下数据,各种不习惯:用mapgis自带的转shp功能,属性表会出错:利用名为map2shp的试用版软件可将mapgis格式的数据较为良好转成shp格式.但经常会遇到一个单位问题 ...
- Java中字节流和字符流的比较(转)
字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢? 实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操 ...
- android Android-PullToRefresh 下拉刷新
1.github下载地址 原作者: https://github.com/chrisbanes/Android-PullToRefresh 我自己的: https://github.com/zyj ...
- [android] SQLite 数据库的升级 和 降级
public class SqliteHelp extends SQLiteOpenHelper { /* * context:创建数据库所需的 上下文对象 * name: 数据库名字 * facto ...
- MQTT for UWP
老规矩,先简单介绍下MQTT: MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协 ...
- IOS 杂笔-4(属性与成员变量的区别)
属性可以用点语法,比如self.xxx,在外部调用也同样可以someClass.xxx. 属性实际上是对一组set和get方法的简单封装(oc的get方法没有get前缀),同样会自动生成一个私有的成员 ...
- 冒泡排序(java版)
public class BubbleSortTest { //冒泡排序 public static void bubbleSort(int[] source) { //外层循环控制控制遍历次数,n个 ...
- iOSQuartz2D-04-手动剪裁图片并保存到相册
实现效果 操作步骤 绘制一个矩形框,弹出一个alertView,提示是否保存图片 点击"是",将图片保存到相册 在相册中查看保存的图片 效果图 实现思路 在控制器的view上添加一 ...