触控点id和索引区别
final int actionIndex = ev.getActionIndex();
final int idBitsToRemove = 1 << ev.getPointerId(actionIndex);
getActionIndex方法,获取触控点索引,索引值和触控手指个数相关,从0开始。触控点索引动态变化,例如三个手指触控,索引是(0,1,2),移除索引是1的手指,索引是(0,1)。
getPointerId(int pointerIndex)方法,根据索引,获取触控点id,触控点id不会改变,从手指触摸到离开的时间段,id都不会改变。
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;
getAction方法,保存事件类型和触控点索引,低8位是事件类型(down,up,move,cancel...),getAction & 0xff,相当于getActionMasked方法,高8位是触控点索引,getAction & 0xff00,相当于getActionIndex方法。
索引值与跟随触控手指个数变化,id不变。
idBitsToRemove是二进制,当前触控点id值代表的位是1,其他位是0,值是不变的。
int pointerCount = event.getPointerCount();
int idBits = 0;
for (int i = 0; i < pointerCount; i++) {
idBits |= 1 << event.getPointerId(i);
}
getPointerCount方法,获取触屏手指总数,索引从0到pointerCount,统计所有触屏手指的id集合,保存在二进制idBits中,id值对应的位设置1。
删除触控点id方法
从TouchTargets中删除触控点id方法。
private void removePointersFromTouchTargets(int pointerIdBits) {
TouchTarget predecessor = null;
TouchTarget target = mFirstTouchTarget;
while (target != null) {
final TouchTarget next = target.next;
if ((target.pointerIdBits & pointerIdBits) != 0) {
target.pointerIdBits &= ~pointerIdBits;
//若不存在任何一位,释放TouchTarget。
if (target.pointerIdBits == 0) {
if (predecessor == null) {
mFirstTouchTarget = next;
} else {
predecessor.next = next;
}
target.recycle();
target = next;
continue;
}
}
predecessor = target;
target = next;
}
}
TouchTarget中的触控点集合,如果触控点pointerId依附在某一项TouchTarget,说明该pointId曾经被TouchTarget的视图消费,被加入TouchTarget位集合。
遍历TouchTargets链表,根据每一个TouchTarget中保存的pointerIdBits集合,查找是否匹配入参触控点id,找到匹配的位,将该位设置0,即清除标识位。
如果整个pointerIdBits变成0,说明在位集合中,仅存在该位,TouchTarget已无用,从链表中删除,recycle释放。
然后,该方法在dispatchTouchEvent中触发的位置。当判断不cancel不intercepted,事件类型down,pointer_down或hover_move时触发。这类情况是第一个手指触屏或新增一个手指触屏,要为该手指触控点pointerId重新分配TouchTarget,如果前面保存过TouchTarget存储着该触控点pointerId,将其删除,防止影响此次触摸。
在第五部分的最终处理时,判断pointer_up事件时触发。触控点pointerId的手指离开屏幕,pointer_up事件,此时仍有其他触控点,这种情况也需要删除触控点pointerId在TouchTarget的存储标志位,触控点pointerId离开,后续将不再影响视图。
任重而道远
网友评论