这两天在做模块的单元测试,需要模拟触屏事件,手势操作,下面针对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; }