Android 多点触控

1.多点触控
多点触控 ( Multitouch,也称 Multi-touch ),即同时接受屏幕上多个点的人机交互操作,多点触控是从 Android 2.0 开始引入的功能,在 Android 2.2 时对这一部分进行了重新设计。

多点触控相关问题:
在引入多点触控之前,事件的类型很少,基本事件类型只有按下(down)、移动(move) 和 抬起(up),即便加上那些特殊的事件类型也只有几种而已,所以我们可以用几个常量来标记这些事件,在使用的时候使用 getAction() 方法来获取具体的事件,之后和这些常量进行对比就行了。
在 Android 2.0 版本的时候,开始引入多点触控技术,由于技术上并不成熟,硬件和驱动也跟不上,多数设备只能支持追踪两三个点而已,因此在设计 API 上采取了一种简单粗暴的方案,添加了几个常量用于多点触控的事件类型的判断。
①ACTION_POINTER_1_DOWN 第 2 个手指按下,已废弃,不推荐使用。
②ACTION_POINTER_2_DOWN 第 3 个手指按下,已废弃,不推荐使用。
③ACTION_POINTER_3_DOWN 第 4 个手指按下,已废弃,不推荐使用。
④ACTION_POINTER_1_UP 第 2 个手指抬起,已废弃,不推荐使用。
⑤ACTION_POINTER_2_UP 第 3 个手指抬起,已废弃,不推荐使用。
⑥ACTION_POINTER_3_UP 第 4 个手指抬起,已废弃,不推荐使用。

这些事件类型是用来判断非主要手指(第一个按下的称为主要手指)的按下和抬起,使用起来大概是这样子:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_POINTER_1_DOWN:
break;
case MotionEvent.ACTION_POINTER_2_DOWN:
break;
case MotionEvent.ACTION_POINTER_3_DOWN:
break;
case MotionEvent.ACTION_POINTER_1_UP:
break;
case MotionEvent.ACTION_POINTER_2_UP:
break;
case MotionEvent.ACTION_POINTER_3_UP:
break;
}
看到这里可能会产生一些疑问?
(1)为什么没有 ACTION_POINTER_X_MOVE ?
在多指触控中所有的移动事件都是使用 ACTION_MOVE, 并没有追踪某一个手指的 move 事件类型。简单说,设备很难无歧义的实现单独追踪每一个手指。
要理解这个,首先要明白设备是如何识别多点触控的,设备没有眼睛,不能像我们人一样看到有几个手指(或者触控笔)在屏幕上。
目前大多数 Android 设备都是电容屏,它们感知触摸是利用手指(触控笔)与屏幕接触产生的微小电流变化,之后通过计算这些电流变化来得出具体的触摸位置,在多点触控中,当两个触摸点足够靠近时,设备实际上是无法分清这两个点的。因此当两个触摸点靠近(重合)后再分开,设备很可能就无法正确的追踪两个点了,所以也很难实现无歧义的追踪每一个点。
并且从软件上来说,事件的编号产生和复用也是一个大问题,例如下面的场景:
事件 手指数量 编号变化
一个手指按下(命名为A) 1 A手指的编号为0,id为0
一个手指按下(命名为B) 2 B手指的编号为1,id为1
A手指抬起 1 B手指编号变更为0,id不变为1
一个手指按下(命名为C) 2 C手指编号为0,id为0,B手指编号为1,id为1

注意观察上面编号和id的变化,有两个问题:
①B手指的编号变化了。
②A手指和C手指id是相同的(A手指抬起后,C手指按下替代了A手指)。

所以这就引出了一个问题:如果存在 ACTION_POINTER_X_MOVE,那么X应该用什么标志呢?编号会变化,id虽然不会变化,但id会被复用,例如A手指抬起后C手指按下,C手指复用了A手指的id。所以不论使用哪一个都不能保证唯一性。

当然了,解决问题最好的方式就是把问题抛出去,既然从硬件和软件上都不能保证唯一性和不变性,就不做区分了,因此所有的 move 事件都是 ACTION_MOVE, 具体是哪个手指产生的 move 用户可以结合其他事件(按下和抬起)来综合判断。

(2)超过4个手指怎么办?
2.0 兼容版,在2.2 之前的设计中,其提供的常量最多能判断四个手指的抬起和落下,当超过四个手指时怎么办呢?在 2.2 版本之前,由于没有 getActionMasked 方法,我们可以自己手动进行计算,例如下面这样 :
int action = event.getAction() & MotionEvent.ACTION_MASK;
int index = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>MotionEvent.ACTION_POINTER_INDEX_SHIFT;
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.e(TAG,“第1个手指按下”);
break;
case MotionEvent.ACTION_UP:
Log.e(TAG,“最后1个手指抬起”);

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值