今天晚上刚学习了一个多点触控的小程序,后面想对其做一个定制。在写的时候遇到很多问题,于是乎就查了一下API文档,又到网上查了一下高手的文章,最后自己又实践了一下。终于把多点触控事件监听的大概原理给弄清楚了。下面就写一下我个人对多点触控原理的理解:

一、MotionEvent事件的分类

触控分为两类:单点触控多点触控

1、如何获取触控事件信息?

安卓中使用32位(int)来存储触控事件的动作信息触控索引。高16位暂时不用,后16位中高8位存储触控信息,低8位存储动作信息。

在安卓当中,使用ACTION_MASK、ACTION_MASK_SHIFT、ACTION_POINTER_INDEX_MASK、ACTION_POINTER_INDEX_SHIFT这四个属性来获得触控事件信息。

属性说明:

ACTION_MASK = 8(0x00ff)  :动作信息掩码,用于截取目标动作信息;

ACTION_MASK_SHIFT = 8(0x00ff) : 截取动作信息时所需移位个数

ACTION_POINTER_INDEX_MASK =65280(0xff00) :高8位的位置信息掩码,用于截取索引信息

ACTION_POINTER_INDEX_SHIFT= 8(0x00ff) :截取触控索引时所需的移位个数

如果我们想要获取当前触控的全部信息,则使用

getAction();返回的是触控的所有信息

如果我们仅仅需要获取当前触控的动作信息,则使用

getActionMasked();返回当前触控的动作信息,即低8位的信息

如果我们想要获取的是当前触控的索引(比如:当你要监听是哪一个手指离开屏幕)

getActionIndex();可以达到效果,返回当前触控动作的索引

2、如何区别动作类型?

在一般的单点触控事件当中,我们只需要使用getAction()得到动作类型,再用ACTION_UP、ACTION_DOWN区分就可以达到目的。但是在多点触控的时候,则需要我

们使用getActionMasked()获得动作信息,然后再区分动作是属于那一类。

动作类型:

ACTION_DOWN  :   第一个手指按下

ACTION_UP    : 最后一个手指离开

ACTION_POINTER_DOWN :非第一个手指按下

ACTION_POINTER_UP : 非最后一个手指离开

ACTION_POINTER_1_DOWN : 这是之前SDK版本所使用的,表示第一个手指按下,它的数值跟ACTION_DOWN是相等的

ACTION_POINTER_2_DOWN:第二根手指按下

ACTION_POINTER_3_DOWN:第三根手指按下

ACTION_POINTER_x_DOWN:第x根手指离开

原理:

取mAction(触控信息)低8位,屏蔽高8位;

即: actionType = (ACTION_MASK&mAction);

例如:mAction= 0x0105H  (表示索引为1动作为:ACTION_DOWN,第一个手指按下)

则:actionType= (0x00ff&0x0105)  = 5 = ACTION_DOWN;

3、如何知道是哪个手指离开?

如果在单点触控的情况下,监听离开直接使用ACTION_UP即可。但如果在多点触控的情况下,就需要我们定位是哪一个手指离开。这个使用就需要使用到getActionIndex()来获取触控动作的索引。从而得知是哪一个点离开了或者哪一个点按下了。

其实getActionIndex()的实现原理很简单:

取mAction(触控动作)高8位信息,然后再右移8位得到索引。

即: Index = (ACTION_POINTER_INDEX_MASK&mACTION)>> ACTION_POINTER_MASK;

例如:mAction = 0x0105H  (表示索引为1动作为:ACTION_DOWN,第一个手指按下)

则:index= (0xff00&0x0105) >> 0x00ff = 1;

二、MotionEvent示例

监听触摸事件(触摸每个点,以点为圆心生成一个不同颜色的小圆和一个交叉的十字,)

示例代码:

@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubint pointerCount = event.getPointerCount();if (pointerCount > MAX_TOUCHPOINTS) {pointerCount = MAX_TOUCHPOINTS;}// 锁定Canvas开始进行相应的界面处理Canvas c =getHolder().lockCanvas();if (c != null) {c.drawColor(Color.BLACK);// 事件类型,也可以使用getActionMasked效果一样
//      int actionType = event.getAction()& MotionEvent.ACTION_MASK;int actionType = event.getActionMasked();switch (actionType) {case MotionEvent.ACTION_DOWN:// 第一个点被按下Toast.makeText(getContext(), "第一个点被按下", Toast.LENGTH_SHORT).show();Toast.makeText(getContext(), "ACTION_POINT_DOWN",Toast.LENGTH_SHORT).show();// 现在屏幕上画一个十字,横向贯穿屏幕,纵向贯穿屏幕//获得触控事件的索引,通过索引获得Pointer的IDint id = event.getPointerId(event.getActionIndex());Toast.makeText(getContext(), "id = " + id, Toast.LENGTH_SHORT).show();int x = (int) event.getX();int y = (int) event.getY();drawCrosshairsAndText(x, y, touchPaints[id], 0, id, c);drawCircle(x, y, touchPaints[id], c);break;case MotionEvent.ACTION_UP:// 最后一个点被释放Toast.makeText(getContext(), "最后一个点被释放", Toast.LENGTH_SHORT).show();break;case MotionEvent.ACTION_POINTER_DOWN:// 非第一个点被按下Toast.makeText(getContext(), "非第一个点被按下", Toast.LENGTH_SHORT).show();// 现在屏幕上画一个十字,横向贯穿屏幕,纵向贯穿屏幕for (int i = 0; i < pointerCount; i++) {// 获取一个触点的坐标,然后开始绘制int id1 = event.getPointerId(i);int x1 = (int) event.getX(i);int y1 = (int) event.getY(i);drawCrosshairsAndText(x1, y1, touchPaints[id1], i, id1, c);}// 使用不同的颜色在每个手指的位置画圆for (int i = 0; i < pointerCount; i++) {int id1 = event.getPointerId(i);Toast.makeText(getContext(),"id = " + id1,Toast.LENGTH_SHORT).show();int x1 = (int) event.getX(i);int y1 = (int) event.getY(i);drawCircle(x1, y1, touchPaints[id1], c);// DrawCircleRun drawCircleRun = new// DrawCircleRun(x,y,id,c);// mRunList[event.getActionIndex()] = drawCircleRun;// mThreadPool.execute(drawCircleRun);}break;case MotionEvent.ACTION_POINTER_UP:// 非最后一个点被释放//获得释放的点的索引和IDint point_index = event.getActionIndex();int point_id = event.getPointerId(point_index);Toast.makeText(getContext(), "非最后一个点被释放:"+"index ="+point_index+"   id = "+point_id, Toast.LENGTH_SHORT).show();break;case MotionEvent.ACTION_MOVE:Toast.makeText(getContext(), "手指移动", Toast.LENGTH_SHORT).show();// 现在屏幕上画一个十字,横向贯穿屏幕,纵向贯穿屏幕for (int i = 0; i < pointerCount; i++) {// 获取一个触点的坐标,然后开始绘制int id1 = event.getPointerId(i);int x1 = (int) event.getX(i);int y1 = (int) event.getY(i);drawCrosshairsAndText(x1, y1, touchPaints[id1], i, id1, c);}// 使用不同的颜色在每个手指的位置画圆for (int i = 0; i < pointerCount; i++) {int id1 = event.getPointerId(i);Toast.makeText(getContext(),"id = " + id1,Toast.LENGTH_SHORT).show();int x1 = (int) event.getX(i);int y1 = (int) event.getY(i);drawCircle(x1, y1, touchPaints[id1], c);// DrawCircleRun drawCircleRun = new// DrawCircleRun(x,y,id,c);// mRunList[event.getActionIndex()] = drawCircleRun;// mThreadPool.execute(drawCircleRun);}break;case MotionEvent.ACTION_SCROLL:Toast.makeText(getContext(), "手指滑动", Toast.LENGTH_SHORT).show();break;case MotionEvent.ACTION_POINTER_2_DOWN:Toast.makeText(getContext(), "第二个手指按下", Toast.LENGTH_SHORT).show();break;case MotionEvent.ACTION_POINTER_3_DOWN:Toast.makeText(getContext(), "第三个手指按下", Toast.LENGTH_SHORT).show();break;case MotionEvent.ACTION_POINTER_3_UP:Toast.makeText(getContext(), "第三个手指离开", Toast.LENGTH_SHORT).show();break;default:break;}}// 画完后,解锁显示getHolder().unlockCanvasAndPost(c);return true;
}

三、为什么要使用掩码和位操作?

很多人,我一开始也疑惑,为什么不从一开始就使用两个整型来存储动作和索引信息呢。这样不是更容易让人理解吗?不过看了API文档的解释之后,才明白这是为了节省内存。因为动作就那么几个,位置信息在高八位以上,还有24位的信息用来存储索引信息(2的24次方个点,绝对够用!)。因此只需要一个32位的整型就可以存储这两个信息。而且计算机内部也只是识别 0\1序列的,我们搞IT的免不了会接触到一些汇编,汇编语言里面的知识在这里就派上用场了,比如:移位、按位逻辑运算等知识。而且熟悉了位存储之后,对于Android的其他类别属性的理解也会更加有帮助。

Android多点触控之——MotionEvent(触控事件)相关推荐

  1. Android多点触控详解

    本文转载自GcsSloop的 安卓自定义View进阶-多点触控详解 的文章 Android 多点触控详解,在前面的几篇文章中我们大致了解了 Android 中的事件处理流程和一些简单的处理方案,本次带 ...

  2. Android多点触控揭秘

    本文原创,转载请注明:http://blog.csdn.net/cloudzfy1/article/details/6582707 Google 暑期大学生博客分享大赛 - 2011 Android ...

  3. Android多点触控技术

    1 简介 Android多点触控在本质上需要LCD驱动和程序本身设计上支持,目前市面上HTC.Motorola和Samsung等知名厂商只要使用电容屏触控原理的手机均可以支持多点触控Multitouc ...

  4. Android 多点触控消息捕获与处理

    1 简介 Android多点触控在本质上需要LCD驱动和程序本身设计上支持,目前市面上HTC.Motorola和Samsung等知名厂商只要使用电容屏触控原理的手机均可以支持多点触控Multitouc ...

  5. Android多点触控之ZoomImageView完全解析

    ZoomImageView是一个类似photoview的图片预览控件,实现了对图片的手势放大缩小平移,以及双击放大缩小解决和viewpager滑动冲突等功能,主要是通过GestureDetector, ...

  6. android motionevent 坐标,Android坐标系、视图坐标系与触控事件(MotionEvent)

    前言:本篇文章讲解Android坐标系.视图坐标系与触控事件(MotionEvent) 一. Android 的坐标系:#### 在Android中,将屏幕左上角的定点座位Android坐标系的原点, ...

  7. 模拟Android多点触控

    Android多点触控 Android多点触控 多点触控实现思路 第一种adb shell input方式 第二种adb shell sendevent方式 多点触控实现思路   经过资料的查询,要在 ...

  8. 如何扩大控件的触控响应区域

    2019独角兽企业重金招聘Python工程师标准>>> 最近在做一个相当奇葩的需求:扩大控件的触控区域,不改变控件大小. 从一个大牛同事那学了一个方法,可惜只能用于父控件内只有一个子 ...

  9. 在带有触控 ID 的妙控键盘上无法正常使用触控 ID的解决方法

    如果您无法使用触控 ID 解锁 Mac.无法注册指纹,或者无法使用触控 ID 输入密码,那我们该怎么办呢?小编给大家带来了详细的解决方法,需要的朋友欢迎参考操作! 检查兼容性 带有触控 ID 的妙控键 ...

最新文章

  1. 洛阳综合保税区正式获国务院批复同意设立
  2. spring boot数据库操作汇总
  3. Windows使用opencv训练模型过程记录(提供样本)
  4. [Windows Phone 7] Storage
  5. 2017.9.26 块的计数 思考记录
  6. centos7虚拟机安装mysql_Linux CentOS7 虚拟机安装mysql教程
  7. conda命令没找到的处理方案
  8. Linux下ioctl函数理解
  9. .net 基础知识大杂烩(2) ——条件语句
  10. oracle错误输出,oracle – SQL小提琴输出错误
  11. 机器学习 —— 神经网络(matlab)
  12. 有哪些好用的游戏加速器推荐?
  13. PROTEL PCB放置汉字
  14. python flask服务器_flask应用部署到服务器
  15. pointer-event属性详解
  16. 老罗如果输了整个民族都输了
  17. 数据同步,数据库实时迁移同步方案,数据库同步软件
  18. Linux 30岁啦,这些历史你知道多少呢?
  19. BZOJ1778: [Usaco2010 Hol]Dotp 驱逐猪猡
  20. 睿赛德科技(RT-Thread)宣布完成A轮融资

热门文章

  1. 冒志鸿将出席 TF Blockchain 波特兰、温哥华 炉边畅谈 SEC 招标 DID | ArcBlock 预告...
  2. MATLAB - 拉普拉斯算子可视化
  3. 伊利洛伊大学厄巴纳-香槟分校计算机专业,申请伊利诺伊大学香槟分校计算机科学专业需要具备哪些条件?看完文章你就清楚了...
  4. win7 两台PC网线直连创建家庭组局域网分享文件
  5. 历史在重演:从KHTML到WebKit,再到Blink
  6. C++基础知识点小结
  7. SkeyeRTSPLive传统视频监控互联网实现利器解决方案
  8. MAC M1大数据0-1成神篇-7 补充CAP模式
  9. 基于C#的单机版连连看游戏设计与实现
  10. centos7 scons安装_安装Python和Scons