前言:上 篇介绍了提供手势绘制的视图平台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。如下代码:

  1. public class GestureOverlayView extends FrameLayout {
  2. ...
  3. private void touchDown(MotionEvent event) {
  4. ...
  5. mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
  6. ...
  7. }
  8. private Rect touchMove(MotionEvent event) {
  9. ...
  10. mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
  11. ...
  12. }
  13. private void touchUp(MotionEvent event, boolean cancel) {
  14. ...
  15. mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
  16. ...
  17. }
  18. ...
  19. }

---->通过上面的代码可知,当用户正在绘制手势时,会调用touchDown、touchMove,执行mStrokeBuffer.add(new
GesturePoint(x, y, event.getEventTime())),实现将点的x、y、event.getEventTime() 值作为GesturePoint的构造函数的实参创建GesturePoint对象,然后将得到的GesturePoint添加到mStrokeBuffer集合中(mStrokeBuffer为ArrayList<GesturePoint>类型);

GesturePoint的源代码如下:

  1. /*
  2. * Copyright (C) 2008-2009 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. *      http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package android.gesture;
  17. import java.io.DataInputStream;
  18. import java.io.IOException;
  19. /**
  20. * A timed point of a gesture stroke. Multiple points form a stroke.
  21. */
  22. //一个手势行程的定时点,多个点形成一个手势行程。GesturePoint封装x,y轴和时间戳的值
  23. public class GesturePoint {
  24. public final float x;
  25. public final float y;
  26. public final long timestamp;
  27. public GesturePoint(float x, float y, long t) {
  28. this.x = x;
  29. this.y = y;
  30. timestamp = t;
  31. }
  32. //从输入流中读取之前保存在文件中的数据
  33. static GesturePoint deserialize(DataInputStream in) throws IOException {
  34. // Read X and Y
  35. final float x = in.readFloat(); //从输入流中读出对应x轴的坐标值 (来自通过调用GestureStroke的函数serialize保存的,下同)
  36. final float y = in.readFloat(); //从输入流中读出对应y轴的坐标值
  37. // Read timestamp
  38. final long timeStamp = in.readLong(); //从输入流中读出对应的时间戳
  39. return new GesturePoint(x, y, timeStamp);
  40. }
  41. @Override
  42. public Object clone() {
  43. return new GesturePoint(x, y, timestamp);
  44. }
  45. }

通过源码可知,在GesturePoint的构造函数中,将传进来的点的各个信息值分别赋值给自身的成员变量x、y、timestamp;所以GesturePoint描述的就是组成完成手势中的一个点元素;而GestureOverlayView中的mStrokeBuffer集合保存着组成手势的多数个点

---->紧接着,当用户完成手势绘制手指离开屏幕时,会调用touchUp,执行 mCurrentGesture.addStroke(new
GestureStroke(mStrokeBuffer)),实现将之前绘制手势得到的mStrokeBuffer集合作为GestureStroke构造函数的实参创建GestureStroke对象,然后将GestureStroke对象作为mCurrentGesture(Gesture对象)的方法addStroke的实参,实现将GestureStroke添加到Gesture中;

GesturePoint的部分源代码如下:

  1. /**
  2. * A gesture stroke started on a touch down and ended on a touch up. A stroke
  3. * consists of a sequence of timed points. One or multiple strokes form a gesture.
  4. */
  5. public class GestureStroke {
  6. ...
  7. public final float length;  //length为手势行程的长度
  8. public final float[] points; //保存组成手势行程的多数个点的x,y坐标值
  9. private final long[] timestamps;//保存组成手势行程的多数个点的时间戳
  10. /**
  11. * A constructor that constructs a gesture stroke from a list of gesture points.
  12. *
  13. * @param points
  14. */
  15. public GestureStroke(ArrayList<GesturePoint> points) {
  16. final int count = points.size();
  17. final float[] tmpPoints = new float[count * 2];
  18. final long[] times = new long[count];
  19. RectF bx = null;
  20. float len = 0;
  21. int index = 0;
  22. for (int i = 0; i < count; i++) {
  23. final GesturePoint p = points.get(i);
  24. tmpPoints[i * 2] = p.x; //偶数位置保存x值
  25. tmpPoints[i * 2 + 1] = p.y; //奇数位置保存x值
  26. times[index] = p.timestamp;
  27. if (bx == null) {
  28. bx = new RectF();
  29. bx.top = p.y;
  30. bx.left = p.x;
  31. bx.right = p.x;
  32. bx.bottom = p.y;
  33. len = 0;
  34. } else {
  35. //Math.pow(a,b)为a的b次方,如Maht.pow(3,2)等于9。下面的公式相当于平方和的根号值
  36. len += Math.sqrt(Math.pow(p.x - tmpPoints[(i - 1) * 2], 2)
  37. + Math.pow(p.y - tmpPoints[(i -1 ) * 2 + 1], 2));
  38. //放大bx覆盖到指定的p.x, p.y点
  39. bx.union(p.x, p.y);
  40. }
  41. index++;
  42. }
  43. timestamps = times;
  44. this.points = tmpPoints;
  45. boundingBox = bx;
  46. length = len;
  47. }
  48. ...
  49. }

通过上面的代码可知,当我们创建GestureStroke的对象时,会执行GestureStroke的构造函数。而在GestureStroke的构造函数中,实现将传进来的mStrokeBuffer集合中封存的多个点进行遍历拆解出来,然后分别赋值给GestureStroke的数组成员变量points,timestamps,同时也根据点的坐标值计算出手势行程的长度length;

---->接着,将创建得到的GestureStroke对象通过调用Gesture的addStroke方法添加到Gesture类的mStrokes中,Gesture的addStroke方法源码实现如下:

  1. /**
  2. * A gesture is a hand-drawn shape on a touch screen. It can have one or multiple strokes.
  3. * Each stroke is a sequence of timed points. A user-defined gesture can be recognized by
  4. * a GestureLibrary.
  5. */
  6. /*手势时是触摸屏上手势绘制的形状,它可以单笔画或者多笔画,
  7. * 每一个笔画是一个计时点序列,用户绘制定义的手势可以通过GestureLibrary来识别
  8. */
  9. public class Gesture implements Parcelable {
  10. ...
  11. private final ArrayList<GestureStroke> mStrokes = new ArrayList<GestureStroke>();
  12. ...
  13. /**
  14. * Adds a stroke to the gesture.
  15. *
  16. * @param stroke
  17. */
  18. public void addStroke(GestureStroke stroke) {
  19. mStrokes.add(stroke);
  20. ...
  21. }
  22. ...
  23. ...
  24. }

所以,在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 源码浅析的更多相关文章

  1. Android 手势识别类 ( 二 ) GestureDetector 源码浅析

    前言:Android 关于手势的操作提供两种形式:一种是针对用户手指在屏幕上划出的动作而进行移动的检测,这些手势的检测通过android提供的监听器来实现:另一种是用 户手指在屏幕上滑动而形成一定的不 ...

  2. 16 BasicHashTable基本哈希表类(三)——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...

  3. Android Handler机制(三)----Looper源码解析

    一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...

  4. Android 手势识别类 ( 一 ) GestureDetector 基本介绍

    为了加强鼠标响应事件,Android提供了GestureDetector手势识别类.通过GestureDetector.OnGestureListener来获取当前被触发的操作手势(Single Ta ...

  5. Android源码浅析(三)——Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机

    Android源码浅析(三)--Android AOSP 5.1.1源码的同步sync和编译make,搭建Samba服务器进行更便捷的烧录刷机 最近比较忙,而且又要维护自己的博客,视频和公众号,也就没 ...

  6. Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令

    Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...

  7. Android开发之Theme、Style探索及源码浅析

    1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...

  8. Android源码浅析(五)——关于定制系统,如何给你的Android应用系统签名

    Android源码浅析(五)--关于定制系统,如何给你的Android应用系统签名 今天来点简单的我相信很多定制系统的同学都会有一些特定功能的需求,比如 修改系统时间 静默安装 执行某shell命令 ...

  9. Android源码浅析(二)——Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境

    Android源码浅析(二)--Ubuntu Root,Git,VMware Tools,安装输入法,主题美化,Dock,安装JDK和配置环境 接着上篇,上片主要是介绍了一些安装工具的小知识点Andr ...

随机推荐

  1. [WP8] 使用ApplicationMenu与使用者互动

    [WP8] 使用ApplicationMenu与使用者互动 范例下载 范例程序代码:点此下载 功能说明 使用过Lumia系列手机的开发人员,对于内建的相机功能相信都很熟悉.在Lumia内建的相机功能中 ...

  2. HTML5原生拖放实例分析

    HTML5提供了原生拖放功能的JavaScript API,使用起来很方便. 兼容性: 对于PC端浏览器,Firefox.Chrome.Safari支持良好,而IE和Edge浏览器有些特性不支持,如I ...

  3. Atitit.图片木马的原理与防范 attilax 总结

    Atitit.图片木马的原理与防范 attilax 总结 1.1. 像图片的木马桌面程序1 1.2. Web 服务端图片木马1 1.3. 利用了Windows的漏洞1 1.4. 这些漏洞不止Windo ...

  4. 桥牌笔记 Skill Level 4 C7 小心将吃

    南主打5H. 看来问题不大,但要小心南的方块AK会阻塞桥路. 如果方块3-2分布,并且将牌也3-2分布,就很容易. 如果红桃4-1分布,那是死定了. 如果方块4-1分布,还有希望完成的! 为了防止东家 ...

  5. Sharepoint学习笔记—习题系列--70-573习题解析 -(Q121-Q124)

    Question 121You develop a custom approval workflow. The workflow uses the CreateTask class to assign ...

  6. DownloadManager 的使用

    一.基本概念    1.DownloadManager是Android 2.3A (API level 9) 引入的,基于http协议,用于处理长时间下载. 2.DownloadManager对于断点 ...

  7. Android根据APP包名启动应用

    public void openApp(String packageName, Context context) { PackageManager packageManager = context.g ...

  8. 转载:sql关联查询

    inner join(等值连接)只返回两个表中联结字段相等的行 left join(左联接)返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接)返回包括右表中的所有记录和 ...

  9. Xcode6.4注册URL Scheme步骤详解

    URL Scheme的作用 我们都知道苹果手机中的APP都有一个沙盒,APP就是一个信息孤岛,相互是不可以进行通信的.但是iOS的APP可以注册自己的URL Scheme,URL Scheme是为方便 ...

  10. iOS开发之网络编程--4、NSURLSessionDataTask实现文件下载(离线断点续传下载) <进度值显示优化>

    前言:根据前篇<iOS开发之网络编程--2.NSURLSessionDownloadTask文件下载>或者<iOS开发之网络编程--3.NSURLSessionDataTask实现文 ...