我们来查看下2个触碰点的MotionEvent log
07-04 09:45:01.052 6686 6686 D test614 : MotionEvent { action=ACTION_DOWN, act
ionButton=0, id[0]=0, x[0]=331.69287, y[0]=619.67725, toolType[0]=TOOL_TYPE_FING
ER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, histor
ySize=0, eventTime=277113574, downTime=277113574, deviceId=8, source=0x1002 }
07-04 09:45:01.800 6686 6686 D test614 : MotionEvent { action=ACTION_POINTER_D
OWN(1), actionButton=0, id[0]=0, x[0]=331.69287, y[0]=619.67725, toolType[0]=TOO
L_TYPE_FINGER, id[1]=1, x[1]=801.2581, y[1]=1427.2566, toolType[1]=TOOL_TYPE_FIN
GER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, histo
rySize=0, eventTime=277114572, downTime=277113574, deviceId=8, source=0x1002 }
07-04 09:45:02.433 6686 6686 D test614 : MotionEvent { action=ACTION_POINTER_U
P(0), actionButton=0, id[0]=0, x[0]=331.69287, y[0]=619.67725, toolType[0]=TOOL_
TYPE_FINGER, id[1]=1, x[1]=801.2581, y[1]=1427.2566, toolType[1]=TOOL_TYPE_FINGE
R, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, history
Size=0, eventTime=277115194, downTime=277113574, deviceId=8, source=0x1002 }
07-04 09:45:03.816 6686 6686 D test614 : MotionEvent { action=ACTION_UP, actio
nButton=0, id[0]=1, x[0]=801.2581, y[0]=1427.2566, toolType[0]=TOOL_TYPE_FINGER,
buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySi
ze=0, eventTime=277116576, downTime=277113574, deviceId=8, source=0x1002 }
MotionEvent打印的code
public String toString() {
StringBuilder msg = new StringBuilder();
msg.append("MotionEvent { action=").append(actionToString(getAction()));
final int pointerCount = getPointerCount();
for (int i = 0; i < pointerCount; i++) {
msg.append(", id[").append(i).append("]=").append(getPointerId(i));
msg.append(", x[").append(i).append("]=").append(getX(i));
msg.append(", y[").append(i).append("]=").append(getY(i));
msg.append(", toolType[").append(i).append("]=").append(
toolTypeToString(getToolType(i)));
}
msg.append(", buttonState=").append(MotionEvent.buttonStateToString(getButtonState()));
msg.append(", metaState=").append(KeyEvent.metaStateToString(getMetaState()));
msg.append(", flags=0x").append(Integer.toHexString(getFlags()));
msg.append(", edgeFlags=0x").append(Integer.toHexString(getEdgeFlags()));
msg.append(", pointerCount=").append(pointerCount);
msg.append(", historySize=").append(getHistorySize());
msg.append(", eventTime=").append(getEventTime());
msg.append(", downTime=").append(getDownTime());
msg.append(", deviceId=").append(getDeviceId());
msg.append(", source=0x").append(Integer.toHexString(getSource()));
msg.append(" }");
return msg.toString();
}
action=ACTION_POINTER_UP(0) 后面显示了index,就知道了是哪个点的操作,根据index可以获得id,当屏幕上有2个点其中一个up了,系统是怎么知道哪一个点up了呢?根据id,坐标,就可以定位到是少(多)了哪个点。
对于ACTION_MOVE,由于经常存在多个点一起move,所以没有必要进行区分,
public final int getActionIndex() {
return (nativeGetAction(mNativePtr) & ACTION_POINTER_INDEX_MASK)
>> ACTION_POINTER_INDEX_SHIFT;
}
所以move的index一般都是 0
由于多个点的数据保存在MotionEvent的内部数组中,通过index去获取各数据,一个index的位置up后,就出现了一个空位,数组结构依次位移。
应用在处理多点事件的时候,由于要处理不断变化的index,有的操作比较复杂,处理的不好,就会出现断触等等点击功能bug
在进行 injectInputEvent的时候,需要构造MotionEvent,管理和控制好各点数据即可,
以scrcpy的处理为例,
private boolean injectTouch(int action, long pointerId, Position position, float pressure, int buttons) {
long now = SystemClock.uptimeMillis();
Point point = device.getPhysicalPoint(position);
if (point == null) {
// ignore event
return false;
}
int pointerIndex = pointersState.getPointerIndex(pointerId);
if (pointerIndex == -1) {
Ln.w("Too many pointers for touch event");
return false;
}
Pointer pointer = pointersState.get(pointerIndex);
pointer.setPoint(point);
pointer.setPressure(pressure);
pointer.setUp(action == MotionEvent.ACTION_UP);
int pointerCount = pointersState.update(pointerProperties, pointerCoords);
if (pointerCount == 1) {
if (action == MotionEvent.ACTION_DOWN) {
lastTouchDown = now;
}
} else {
// secondary pointers must use ACTION_POINTER_* ORed with the pointerIndex
if (action == MotionEvent.ACTION_UP) {
action = MotionEvent.ACTION_POINTER_UP | (pointerIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
} else if (action == MotionEvent.ACTION_DOWN) {
action = MotionEvent.ACTION_POINTER_DOWN | (pointerIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
}
}
MotionEvent event = MotionEvent
.obtain(lastTouchDown, now, action, pointerCount, pointerProperties, pointerCoords, 0, buttons, 1f, 1f, DEVICE_ID_VIRTUAL, 0,
InputDevice.SOURCE_TOUCHSCREEN, 0);
return device.injectEvent(event);
}
public int update(MotionEvent.PointerProperties[] props, MotionEvent.PointerCoords[] coords) {
int count = pointers.size();
for (int i = 0; i < count; ++i) {
Pointer pointer = pointers.get(i);
// id 0 is reserved for mouse events
props[i].id = pointer.getLocalId();
Point point = pointer.getPoint();
coords[i].x = point.getX();
coords[i].y = point.getY();
coords[i].pressure = pointer.getPressure();
}
cleanUp();
return count;
}