android 多点MotionEvent的构建,多点操作屏幕,多点触碰屏幕
论android 多点触碰的构建。可以用于外设对于手机的多点操控,比如说手柄,键鼠等
1.我们先分析一下多个手点击滑动得到的MotionEvent。在view 重写onTouchEvent的方法,打印内容
2.分析的内容,这边不做详细的截图,自己去打印查看,我们分析两个点,开始一个点是Action=ACTION_DOWN,然后move,id就是0,点下第二个点,action=ACTION_POINTER_DOWN(1),id为1,第一个点的id还是0,并且可以看到两个点的坐标都是存在的,也就是这个MotionEvent是带着两个点的,接着释放一个点,这个时候你会看到如果释放的是第二个点,action=ACTION_POINTER_UP(1),如果释放的是第一个点,那么action=ACTION_POINTER_UP(0),当释放最后一个点的时候action=ACTION__UP
3.以此类推,三个点,四个点,就是ACTION_POINTER_DOWN(2)ACTION_POINTER_UP(2),每个点都是有id标识的,下标从0开始,点下的点跟释放的点都是同一个id。
4.创建多点,需要拿到action,sid,坐标。实现逻辑 当down下的时候,记录点下的点的id,id是从0开始,并且如果按下0,按下1,按下2,释放1,再按下id就是1,也就是说从0开始,如果中间某个id不存在就记录为当前的id,当move的时候就沿用这个id,当up的时候就移除这个uselist的对象,
public void down(int keycode, int x, int y) {
synchronized (lock) {
try {
GamePadEvent target = new GamePadEvent(keycode);
//把新的target 添加到usedlist里面去,并且设置sid
if (usedList.size() > 0) {
int i;
for (i = 0; i < 10; i++) {//写了10就是支持10个点
boolean found = false;
for (GamePadEvent each : usedList) {
if (each.sid == i) {
found = true;
break;
}
}
if (!found)
break;
}
target.sid = i;
usedList.add(i, target);
} else {
target.sid = 0;
usedList.add(0, target);
}
MotionEvent event = getMultiEvent(target);
//注入这里不写明,不同环境使用方法不一样,当前应用可以使用下面方法的去测试
Instrumentation mInst = new Instrumentation();
if (event != null)
mInst.sendPointerSync(event.getMotionEvent());
} catch (Exception e) {
e.printStackTrace();
}
}
}
5.重点是多点的构建,PointerProperties 主要构建sid,就是刚刚保存的id ,从下标0开始算,PointerCoords 主要是构建坐标, MotionEvent.obtain(),方式去构建一个新的MotionEvent。
private MotionEvent getMultiEvent(GamePadEvent target) {
if (usedList.size() == 0)
return null;
long when = SystemClock.uptimeMillis();
int action = MotionEvent.ACTION_MOVE;
//记录当前按下的点的action是move,up,down,判断点是2个点还是一个点,记录当前的action,方便后面做计算
if (target.action == MotionEvent.ACTION_DOWN)
action = usedList.size() > 1 ? MotionEvent.ACTION_POINTER_DOWN : MotionEvent.ACTION_DOWN;
if (target.action == MotionEvent.ACTION_UP)
action = usedList.size() > 1 ? MotionEvent.ACTION_POINTER_UP : MotionEvent.ACTION_UP;
PointerProperties[] pointerProperties = new PointerProperties[usedList.size()];
PointerCoords[] pointerCoords = new PointerCoords[usedList.size()];
int index = 0;
int targetIndex = 0;
LogUtils.logI(" getMultiEvent usedList size :" + usedList.size());
for (GamePadEvent gamePadEvent : usedList) {
PointerCoords pointerCoord = new PointerCoords();
pointerCoord.pressure = 1;
pointerCoord.x = gamePadEvent.x;//x坐标
pointerCoord.y = gamePadEvent.y;//yx坐标
pointerCoords[index] = pointerCoord;
PointerProperties pointerPropertie = new PointerProperties();
pointerPropertie.id = gamePadEvent.sid;//保存的id
pointerPropertie.toolType = 1;
pointerProperties[index] = pointerPropertie;
if (gamePadEvent.keycode == target.keycode) {
targetIndex = index;//记录当前的按下的点的位置,用作计算最后的action
}
++index;
}
//这是计算最后的点的action,前面通过多点,单点判断得到了action,就位移计算,等到最后的值,如果是move事件,多点的action还是move,如果是其它两个down,up,
int actionPoint = (action != MotionEvent.ACTION_MOVE) ? (action + (targetIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT)) : MotionEvent.ACTION_MOVE;
return MotionEvent.obtain(when, when, actionPoint, usedList.size(), pointerProperties, pointerCoords, 0, 0, 1, 1, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
}
6.最后,如果有什么疑问,可以联系我。暂时没有编写demo,有空再编写