这两天在做模块的单元测试,需要模拟触屏事件,手势操作,下面针对MotionEvent做下代码记录:
下面的事件注入都会调用一个函数:
Instrumentation mInstrumentation;
public void sendPointerEvent(int action, Point point) {
MotionEvent event = MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), action, point.x, point.y, 0);
mInstrumentation.sendPointerSync(event);
event.recycle();
}
1,MotionEvent.ACTION_DOWN
Down跟UP通常是连着的。
Point selectPoint = new Point(670,470);
sendPointerEvent(MotionEvent.ACTION_DOWN, selectPoint);
sendPointerEvent(MotionEvent.ACTION_UP, selectPoint);
2,MotionEvent.ACTION_MOVE
从一个Down事件开始,中间loop多个Move,最后一个Up事件。
Point from = new Point(150, 650);
Point to = new Point(150, 260);
sendPointerEvent(MotionEvent.ACTION_DOWN, from);
MovePointerEvent(from, to, 10, 10);
sendPointerEvent(MotionEvent.ACTION_UP, to);
这里计算move的步进:
private int getNextMoveValue(int oldValue, int targetValue, int distance, int step) {
if (targetValue - oldValue > distance) {
return oldValue + step;
} else if (targetValue - oldValue < -distance) {
return oldValue - step;
} else {
return targetValue;
}
}
3,手势操作,缩放
private int PINCH_STEP_COUNT = 10;
public void scaleGestureDetector() {
try {
final float initialScaleFactor = 1.0f;
final DisplayMetrics dm = new DisplayMetrics();
final WindowManager wm =
(WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
//obtain the display size ,so that to get start and end coordinates.
wm.getDefaultDisplay().getMetrics(dm);
final int displayWidth = dm.widthPixels;
final int displayHeight = dm.heightPixels;
//from center,pinch to 75% of display.
final int centerX = displayWidth / 2;
final int centerY = displayHeight / 2;
final float[] firstFingerStartCoords = new float[] {centerX + 1.0f, centerY - 1.0f};
final float[] firstFingerEndCoords =
new float[] {0.75f * displayWidth, 0.25f * displayHeight};
//the second point different from the first.
final float[] secondFingerStartCoords = new float[] {centerX - 1.0f, centerY + 1.0f};
final float[] secondFingerEndCoords =
new float[] {0.25f * displayWidth, 0.75f * displayHeight};
//specify the touch properites.
final MotionEvent.PointerProperties pp1 = new MotionEvent.PointerProperties();
pp1.id = 0;
pp1.toolType = MotionEvent.TOOL_TYPE_FINGER;
final MotionEvent.PointerProperties pp2 = new MotionEvent.PointerProperties();
pp2.id = 1;
pp2.toolType = MotionEvent.TOOL_TYPE_FINGER;
MotionEvent.PointerProperties[] pointerProperties =
new MotionEvent.PointerProperties[]{pp1, pp2};
//specify the motion properites.
final MotionEvent.PointerCoords pc1 = new MotionEvent.PointerCoords();
pc1.x = firstFingerStartCoords[0];
pc1.y = firstFingerStartCoords[1];
pc1.pressure = 1;
pc1.size = 1;
final MotionEvent.PointerCoords pc2 = new MotionEvent.PointerCoords();
pc2.x = secondFingerStartCoords[0];
pc2.y = secondFingerEndCoords[1];
pc2.pressure = 1;
pc2.size = 1;
final long startTime = SystemClock.uptimeMillis();
long eventTime = startTime;
final MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[]{pc1, pc2};
final MotionEvent firstFingerEvent = MotionEvent.obtain(startTime,
eventTime, MotionEvent.ACTION_DOWN, 1, pointerProperties, pointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
eventTime = SystemClock.uptimeMillis();
final MotionEvent secondFingerEvent = MotionEvent.obtain(startTime, eventTime,
MotionEvent.ACTION_POINTER_DOWN +
(pp2.id << MotionEvent.ACTION_POINTER_INDEX_SHIFT),
2, pointerProperties, pointerCoords, 0, 0, 1, 1, 0, 0, 0, 0);
//inject the start down event.
mInstrumentation.sendPointerSync(firstFingerEvent);
mInstrumentation.sendPointerSync(secondFingerEvent);
final float[][] stepsFirstFinger = interpolate(firstFingerStartCoords,
firstFingerEndCoords);
final float[][] stepsSecondFinger = interpolate(secondFingerStartCoords,
secondFingerEndCoords);
//loop the motion of two fingers to the end points.
for (int i = 0; i < PINCH_STEP_COUNT; i++) {
eventTime = SystemClock.uptimeMillis();
pc1.x = stepsFirstFinger[i][0];
pc1.y = stepsFirstFinger[i][1];
pc2.x = stepsSecondFinger[i][0];
pc2.y = stepsSecondFinger[i][1];
final MotionEvent event = MotionEvent.obtain(startTime, eventTime,
MotionEvent.ACTION_MOVE, 2, pointerProperties, pointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
mInstrumentation.sendPointerSync(event);
Thread.sleep(TIMEWAITING*4/5);
}
eventTime = SystemClock.uptimeMillis();
final MotionEvent secondFingerUpEvent = MotionEvent.obtain(startTime, eventTime,
MotionEvent.ACTION_POINTER_UP, 2, pointerProperties, pointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
//inject the up event.
mInstrumentation.sendPointerSync(secondFingerUpEvent);
eventTime = SystemClock.uptimeMillis();
final MotionEvent firstFingerUpEvent = MotionEvent.obtain(startTime, eventTime,
MotionEvent.ACTION_POINTER_UP, 1, pointerProperties, pointerCoords,
0, 0, 1, 1, 0, 0, 0, 0);
mInstrumentation.sendPointerSync(firstFingerUpEvent);
}catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
两个手指移动的差值计算:
private float[][] interpolate(float[] start, float[] end) {
float[][] res = new float[PINCH_STEP_COUNT][2];
for (int i = 0; i < PINCH_STEP_COUNT; i++) {
res[i][0] = start[0] + (end[0] - start[0]) * i / (PINCH_STEP_COUNT - 1f);
res[i][1] = start[1] + (end[1] - start[1]) * i / (PINCH_STEP_COUNT - 1f);
}
return res;
}