设为首页收藏本站
机战Z2破界篇 星组汉化 下载

星组游戏论坛

 找回密码
 注册(QQ注册+邀请注册)

QQ登录

只需一步,快速开始

查看: 2213|回复: 5

[心得] Android多点触控的一些思路 [复制链接]

Rank: 11Rank: 11Rank: 11Rank: 11

UID
95061
星币
5191
积分
814
阅读权限
90
注册时间
2012-12-5
最后登录
2018-9-29
发表于 2012-12-10 17:48:37 |显示全部楼层
本帖最后由 MythosMa 于 2012-12-13 15:28 编辑 ; Q4 w$ U; g' I% _3 t6 S
4 Q0 f  M5 l! ?% |  c
           多点触控实际上并没有想象中的复杂,因为它在OnTouchEvent中已经包含了处理多点的一些方法,这里我们先看看其参数MotionEvent所拥有的部分方法。
  1. event.getAction() //获取触控动作比如ACTION_DOWN  5 F3 V2 O# \* |# v$ ?$ f4 T
  2. event.getPointerCount(); //获取触控点的数量,比如2则可能是两个手指同时按压屏幕  3 @: W4 L9 d- q, c# C, U* Y; E
  3. event.getPointerId(nID); //对于每个触控的点的细节,我们可以通过一个循环执行getPointerId方法获取索引  
    : }1 m7 M7 g$ Y8 O  Y
  4. event.getX(nID); //获取第nID个触控点的x位置  & Y! C) A2 G1 }9 Q4 g% T8 W/ d
  5. event.getY(nID); //获取第nID个点触控的y位置  
    " n% D9 h5 ]2 F! V3 I
  6. event.getPressure(nID); //LCD可以感应出用户的手指压力,当然具体的级别由驱动和物理硬件决定的  1 J" d, X5 a8 b' b3 s6 n
  7. event.getDownTime() //按下开始时间  7 U, z$ ?+ g9 O2 d, E
  8. event.getEventTime() // 事件结束时间  8 ?" x  x' q  F8 h' w5 b1 P
  9. event.getEventTime()-event.getDownTime()); //总共按下时花费时间  
复制代码
我们可以看到,其中有两个方法:event.getPointerCount()和event.getPointerId(nID),通过这两个方法就能获取到多点的信息。那么我们遍历event.getPointerId(nID)获得到对应点的ID,再通过event.getX(nID)和event.getY(nID)这两个方法获取到对应点的坐标,就能在这个点上操作了。  B$ p6 q7 T5 W
          具体代码请看附件中的工程。. ?& m$ d: q  R' ?7 G. o
          不过这个实现方法还存在一个问题,当多点按下后,抬起一个点,其他点保持不动,OnTouchEvent事件虽然捕捉到了,但是图像上的点没有消失。不知道是不是没有使用线程去刷新画布这样的做法去做导致的。哪位有心可以试一试,在这里我只是给大家提供个思路。( _: M6 N& P( H6 ~+ Q. O3 [7 ]

- z2 b+ @$ o; U$ R- x. t          做出一点补充,关于触屏操作的ID和索引的一些区别,以及如何去判定移开的是哪个手指,下面以两点触摸为例:          手指(触摸)索引:当前手指是第几个触摸的手指,如果前面的手指离开了,索引会减少。[比如 原本是1 但是前面的0离开了 ,1就变成了0]
- s. p6 O# H8 ]6 T; r: {/ t. X          手指(触摸)ID:当手指触摸后就会分配给他ID,手指离开不会对其他手指ID影响,但是新进入的手指ID会从0开始找到一个没有使用的id(比如ID 0 ,1 如果0 离开了 1不变,但是新进入的并不是2,而是重新使用0)7 H9 {5 X. B" g6 |9 f2 _0 R
          总结一下:, Z! j- V# H' N5 @$ |: |" K
          引索至于当前手指触摸的顺序有关。7 N6 k, ?. `0 q# O& N1 j% `
          而ID是已进入即不可改变,且数字不留空。后面进来的会补充空缺的。        
; S8 R) y( m" p5 D          触摸状态的变换: ) ]+ e1 M' p0 p- |& r+ C8 l

          先说下action的值:

          简单的说就是id*256+多点action(多点时:down 5     up 6    move 2       单点时: down 0    up 1      move 2)

          其实第二个体手指按下的action值是16进制数0×00000105 的值,第二个字节表示id 第一个字节表示action(多点时:down 5     up 6    move 2       单点时: down 0    up 1      move 2)

          一、在多点触摸时,第二个手指先离开。7 P  [! K* R" D8 U# _
                1:当点下第一个点时 action应该是0,此时还是认为是单点触摸。此时此手指引索为0,ID为0;% ]4 X: s* i! x9 z8 h5 L2 z4 N& V5 I
                2:当殿下第二个点时:action应该是261。第二个手指的引索为1     ID为1。此时已经被认为是多点触摸了。+ C! |! \% L' J( Z. i
                3 : 当松开第二个手指时,action应该为:262,(256+6):此时认为是多点触摸离开一个手指。4 D6 ]# O4 l8 G
                4:再松开第一个手指时,action应该为:1此时只有一个手指在屏幕上,所以认为是单点触摸。

         二、第一个手指先离开
9 a* l* o2 U1 x6 N5 D4 l; A                与上1,2相同( g& U" L9 Y3 ^" D; [* T; ]0 N  q2 d8 U
                3,当松开第一个手指时:action应该为:6(0*256+6)。此时认为是多点触摸。ID为0的手指离开。第二个手指的引索变为0,id还是1.
$ C: S8 C) J0 ]% D. R                4: 当第二个手指 离开时,action为:1。此时如果按照前面的理论应该输出262(1*256+6) 但是android认为最后一个来开的手指触发的action必为1。

         三、第一个手指先离开再按回来。. @& j( l2 v. Y! E% c4 V
                与上1,2相同
( H6 i9 P8 k% `+ U1 C% i                3,当松开第一个手指时:action应该为:6(0*256+6)。 此时认为是多点触摸。ID为0的手指离开。第二个手指的引索变为0,id还是1.5 ~1 i$ k$ n9 d3 k4 M: [5 m  A
                4,当点回第一个手指时:aciton应该为:6。此时认为是多点触摸。ID为0的手指进入,引索为1。[此时第二个手指id为1,引索为0]
7 C3 q9 R' @( W2 O  F                 [新进入的手指会从0开始找ID如果 空缺就是用 而引索只是触摸的时间上的先后顺序来决定的]

                5,当第二个手指离开时:action应该为:262(256+6)。如一的3~4

         最后,对event.getAction()的处理:


5 X2 n, z! [! I6 j% Q+ G
  1. pointerAction = event.getAction();
    8 ^- v; }/ g9 q; D! q: S# ?
  2. 5 T% H" c7 {2 N% u  r
  3. pointerId = event.getPointerId(0);//通过索引值得到id
    - ^# ]4 F$ Q0 N( u: U

  4. : T* c1 b( \- B, S
  5. if (event.getPointerCount() > 1) {// 手指触摸多于一个 与运算 和移位运算得出 pointerId;6 l& G) {6 i* v2 [. \1 O5 L
  6. 6 F  c* M  T, V3 a7 N5 M7 M
  7. pointerId = (pointerAction & MotionEvent.ACTION_POINTER_ID_MASK) >>>
    1 ]& E2 z4 x5 d, N
  8. 5 K( O& b% L' Z
  9. MotionEvent.ACTION_POINTER_ID_SHIFT;) U) d( x, B. ~9 f4 I# `1 s% k

  10. + Y9 r! _+ N/ k2 x( I9 \
  11. }7 G- ^2 h( `1 e, n" \9 |

  12. 8 |4 k4 Y1 Q7 B2 r) k/ c2 o0 W
  13. // 与运算得出 PointerAction 得到Action Down , move or Up( z0 i, @: F: h& n( t3 m2 f+ Z+ N" w1 ?

  14. + ?( s, ~3 v7 I1 B  k
  15. pointerAction = (event.getAction() & MotionEvent.ACTION_MASK) % 5;
    " Q2 B. G" _9 H) x) u4 O  s# n
  16. * `4 V& \6 R" g1 z' ^
  17. // 根据pointer id 找到 对应的索引值, _1 C4 J0 `7 ?5 d1 K8 I

  18. 1 S. y- `3 I) H9 Y/ T0 T! J" @
  19. pointerIndex = event.findPointerIndex(pointerId);2 [) ~" P- C- I' q5 f9 f
  20. 3 B0 Q) p1 I1 o$ Y% ^( \
  21. }
复制代码
5 v& \# Y" K) k. i$ t
          注:已经研究好了抬起手指提示图消失的问题,是由于离开手指操作的判定问题,综合了上述关于ID和索引的做法后,修改了相关工程。
8 S# b; E  _" ?! @8 W6 D; G* T
. P$ z7 f& g+ l          MultiTouch.rar (919.04 KB, 下载次数: 31) : o/ V4 U& ]. Q- w& g8 _2 N

0 ^( x/ s* U0 N) J$ J9 L$ o; y: M7 m4 F& n
Freely Tomorrow

管理员

勇者

Rank: 24Rank: 24Rank: 24Rank: 24Rank: 24Rank: 24

UID
4
星币
347
积分
5129
阅读权限
255
注册时间
2007-6-30
最后登录
2018-10-22
发表于 2012-12-10 19:38:57 |显示全部楼层
这个首先还是需要检测 硬件是否支持多点吧。" H- |) K. M- w. j& k# _+ S
星组游戏开发组 急招游戏画师美工~~~详见链接点我进入招募贴

Rank: 11Rank: 11Rank: 11Rank: 11

UID
95061
星币
5191
积分
814
阅读权限
90
注册时间
2012-12-5
最后登录
2018-9-29
发表于 2012-12-11 08:32:52 |显示全部楼层
绝世爱笑 发表于 2012-12-10 19:38
* c5 r1 M& [8 P: X/ D& ]. q0 T这个首先还是需要检测 硬件是否支持多点吧。

  }! d; E. K6 W* X0 V% s7 u这个还真没试,不过我在猜想用这个方法的话,设备不支持多点event.getPointerCount这个方法应该只能捕捉到1,而不会发生错误。
Freely Tomorrow

Rank: 1

UID
97918
星币
13
积分
2
阅读权限
10
注册时间
2013-3-29
最后登录
2013-3-29
发表于 2013-3-29 13:51:46 |显示全部楼层
多点
头像被屏蔽

禁止发言

UID
109963
星币
27
积分
122
阅读权限
0
注册时间
2015-10-8
最后登录
2015-10-13
发表于 2015-10-12 21:45:24 |显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

Rank: 2

UID
114887
星币
18
积分
90
阅读权限
20
注册时间
2016-3-3
最后登录
2016-3-5
发表于 2016-3-4 20:37:31 |显示全部楼层
这么好的帖子不顶就太对不起楼主了

Archiver|星组游戏论坛 ( 京公网安备110403080002 )  

GMT+8, 2018-10-23 15:30

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部