/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.test;
import android.app.Activity;
import android.app.Instrumentation;
import android.graphics.Point;
import android.os.SystemClock;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
/**
* Reusable methods for generating touch events. These methods can be used with
* InstrumentationTestCase or ActivityInstrumentationTestCase2 to simulate user interaction with
* the application through a touch screen.
*
* @deprecated Use
* <a href="{@docRoot}training/testing/ui-testing/espresso-testing.html">Espresso UI testing
* framework</a> instead. New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public class TouchUtils {
/**
* Simulate touching in the center of the screen and dragging one quarter of the way down
* @param test The test case that is being run
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void dragQuarterScreenDown(ActivityInstrumentationTestCase test) {
dragQuarterScreenDown(test, test.getActivity());
}
/**
* Simulate touching in the center of the screen and dragging one quarter of the way down
* @param test The test case that is being run
* @param activity The activity that is in the foreground of the test case
*/
public static void dragQuarterScreenDown(InstrumentationTestCase test, Activity activity) {
Display display = activity.getWindowManager().getDefaultDisplay();
final Point size = new Point();
display.getSize(size);
final float x = size.x / 2.0f;
final float fromY = size.y * 0.5f;
final float toY = size.y * 0.75f;
drag(test, x, x, fromY, toY, 4);
}
/**
* Simulate touching in the center of the screen and dragging one quarter of the way up
* @param test The test case that is being run
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void dragQuarterScreenUp(ActivityInstrumentationTestCase test) {
dragQuarterScreenUp(test, test.getActivity());
}
/**
* Simulate touching in the center of the screen and dragging one quarter of the way up
* @param test The test case that is being run
* @param activity The activity that is in the foreground of the test case
*/
public static void dragQuarterScreenUp(InstrumentationTestCase test, Activity activity) {
Display display = activity.getWindowManager().getDefaultDisplay();
final Point size = new Point();
display.getSize(size);
final float x = size.x / 2.0f;
final float fromY = size.y * 0.5f;
final float toY = size.y * 0.25f;
drag(test, x, x, fromY, toY, 4);
}
/**
* Scroll a ViewGroup to the bottom by repeatedly calling
* {@link #dragQuarterScreenUp(InstrumentationTestCase, Activity)}
*
* @param test The test case that is being run
* @param v The ViewGroup that should be dragged
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void scrollToBottom(ActivityInstrumentationTestCase test, ViewGroup v) {
scrollToBottom(test, test.getActivity(), v);
}
/**
* Scroll a ViewGroup to the bottom by repeatedly calling
* {@link #dragQuarterScreenUp(InstrumentationTestCase, Activity)}
*
* @param test The test case that is being run
* @param activity The activity that is in the foreground of the test case
* @param v The ViewGroup that should be dragged
*/
public static void scrollToBottom(InstrumentationTestCase test, Activity activity,
ViewGroup v) {
ViewStateSnapshot prev;
ViewStateSnapshot next = new ViewStateSnapshot(v);
do {
prev = next;
TouchUtils.dragQuarterScreenUp(test, activity);
next = new ViewStateSnapshot(v);
} while (!prev.equals(next));
}
/**
* Scroll a ViewGroup to the top by repeatedly calling
* {@link #dragQuarterScreenDown(InstrumentationTestCase, Activity)}
*
* @param test The test case that is being run
* @param v The ViewGroup that should be dragged
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void scrollToTop(ActivityInstrumentationTestCase test, ViewGroup v) {
scrollToTop(test, test.getActivity(), v);
}
/**
* Scroll a ViewGroup to the top by repeatedly calling
* {@link #dragQuarterScreenDown(InstrumentationTestCase, Activity)}
*
* @param test The test case that is being run
* @param activity The activity that is in the foreground of the test case
* @param v The ViewGroup that should be dragged
*/
public static void scrollToTop(InstrumentationTestCase test, Activity activity, ViewGroup v) {
ViewStateSnapshot prev;
ViewStateSnapshot next = new ViewStateSnapshot(v);
do {
prev = next;
TouchUtils.dragQuarterScreenDown(test, activity);
next = new ViewStateSnapshot(v);
} while (!prev.equals(next));
}
/**
* Simulate touching the center of a view and dragging to the bottom of the screen.
*
* @param test The test case that is being run
* @param v The view that should be dragged
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void dragViewToBottom(ActivityInstrumentationTestCase test, View v) {
dragViewToBottom(test, test.getActivity(), v, 4);
}
/**
* Simulate touching the center of a view and dragging to the bottom of the screen.
*
* @param test The test case that is being run
* @param activity The activity that is in the foreground of the test case
* @param v The view that should be dragged
*/
public static void dragViewToBottom(InstrumentationTestCase test, Activity activity, View v) {
dragViewToBottom(test, activity, v, 4);
}
/**
* Simulate touching the center of a view and dragging to the bottom of the screen.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param stepCount How many move steps to include in the drag
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void dragViewToBottom(ActivityInstrumentationTestCase test, View v,
int stepCount) {
dragViewToBottom(test, test.getActivity(), v, stepCount);
}
/**
* Simulate touching the center of a view and dragging to the bottom of the screen.
*
* @param test The test case that is being run
* @param activity The activity that is in the foreground of the test case
* @param v The view that should be dragged
* @param stepCount How many move steps to include in the drag
*/
public static void dragViewToBottom(InstrumentationTestCase test, Activity activity, View v,
int stepCount) {
int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
int[] xy = new int[2];
v.getLocationOnScreen(xy);
final int viewWidth = v.getWidth();
final int viewHeight = v.getHeight();
final float x = xy[0] + (viewWidth / 2.0f);
float fromY = xy[1] + (viewHeight / 2.0f);
float toY = screenHeight - 1;
drag(test, x, x, fromY, toY, stepCount);
}
/**
* Simulate touching the center of a view and releasing quickly (before the tap timeout).
*
* @param test The test case that is being run
* @param v The view that should be clicked
*/
public static void tapView(InstrumentationTestCase test, View v) {
int[] xy = new int[2];
v.getLocationOnScreen(xy);
final int viewWidth = v.getWidth();
final int viewHeight = v.getHeight();
final float x = xy[0] + (viewWidth / 2.0f);
float y = xy[1] + (viewHeight / 2.0f);
Instrumentation inst = test.getInstrumentation();
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime,
MotionEvent.ACTION_DOWN, x, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
eventTime = SystemClock.uptimeMillis();
final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
}
/**
* Simulate touching the center of a view and cancelling (so no onClick should
* fire, etc).
*
* @param test The test case that is being run
* @param v The view that should be clicked
*/
public static void touchAndCancelView(InstrumentationTestCase test, View v) {
int[] xy = new int[2];
v.getLocationOnScreen(xy);
final int viewWidth = v.getWidth();
final int viewHeight = v.getHeight();
final float x = xy[0] + (viewWidth / 2.0f);
float y = xy[1] + (viewHeight / 2.0f);
Instrumentation inst = test.getInstrumentation();
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime,
MotionEvent.ACTION_DOWN, x, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
eventTime = SystemClock.uptimeMillis();
final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_CANCEL,
x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
}
/**
* Simulate touching the center of a view and releasing.
*
* @param test The test case that is being run
* @param v The view that should be clicked
*/
public static void clickView(InstrumentationTestCase test, View v) {
int[] xy = new int[2];
v.getLocationOnScreen(xy);
final int viewWidth = v.getWidth();
final int viewHeight = v.getHeight();
final float x = xy[0] + (viewWidth / 2.0f);
float y = xy[1] + (viewHeight / 2.0f);
Instrumentation inst = test.getInstrumentation();
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime,
MotionEvent.ACTION_DOWN, x, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
eventTime = SystemClock.uptimeMillis();
final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Simulate touching the center of a view, holding until it is a long press, and then releasing.
*
* @param test The test case that is being run
* @param v The view that should be clicked
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void longClickView(ActivityInstrumentationTestCase test, View v) {
longClickView((InstrumentationTestCase) test, v);
}
/**
* Simulate touching the center of a view, holding until it is a long press, and then releasing.
*
* @param test The test case that is being run
* @param v The view that should be clicked
*/
public static void longClickView(InstrumentationTestCase test, View v) {
int[] xy = new int[2];
v.getLocationOnScreen(xy);
final int viewWidth = v.getWidth();
final int viewHeight = v.getHeight();
final float x = xy[0] + (viewWidth / 2.0f);
float y = xy[1] + (viewHeight / 2.0f);
Instrumentation inst = test.getInstrumentation();
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime,
MotionEvent.ACTION_DOWN, x, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
eventTime = SystemClock.uptimeMillis();
final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
x + touchSlop / 2, y + touchSlop / 2, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
try {
Thread.sleep((long)(ViewConfiguration.getLongPressTimeout() * 1.5f));
} catch (InterruptedException e) {
e.printStackTrace();
}
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
}
/**
* Simulate touching the center of a view and dragging to the top of the screen.
*
* @param test The test case that is being run
* @param v The view that should be dragged
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void dragViewToTop(ActivityInstrumentationTestCase test, View v) {
dragViewToTop((InstrumentationTestCase) test, v, 4);
}
/**
* Simulate touching the center of a view and dragging to the top of the screen.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param stepCount How many move steps to include in the drag
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void dragViewToTop(ActivityInstrumentationTestCase test, View v, int stepCount) {
dragViewToTop((InstrumentationTestCase) test, v, stepCount);
}
/**
* Simulate touching the center of a view and dragging to the top of the screen.
*
* @param test The test case that is being run
* @param v The view that should be dragged
*/
public static void dragViewToTop(InstrumentationTestCase test, View v) {
dragViewToTop(test, v, 4);
}
/**
* Simulate touching the center of a view and dragging to the top of the screen.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param stepCount How many move steps to include in the drag
*/
public static void dragViewToTop(InstrumentationTestCase test, View v, int stepCount) {
int[] xy = new int[2];
v.getLocationOnScreen(xy);
final int viewWidth = v.getWidth();
final int viewHeight = v.getHeight();
final float x = xy[0] + (viewWidth / 2.0f);
float fromY = xy[1] + (viewHeight / 2.0f);
float toY = 0;
drag(test, x, x, fromY, toY, stepCount);
}
/**
* Get the location of a view. Use the gravity param to specify which part of the view to
* return.
*
* @param v View to find
* @param gravity A combination of (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL,
* RIGHT)
* @param xy Result
*/
private static void getStartLocation(View v, int gravity, int[] xy) {
v.getLocationOnScreen(xy);
final int viewWidth = v.getWidth();
final int viewHeight = v.getHeight();
switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
case Gravity.TOP:
break;
case Gravity.CENTER_VERTICAL:
xy[1] += viewHeight / 2;
break;
case Gravity.BOTTOM:
xy[1] += viewHeight - 1;
break;
default:
// Same as top -- do nothing
}
switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
break;
case Gravity.CENTER_HORIZONTAL:
xy[0] += viewWidth / 2;
break;
case Gravity.RIGHT:
xy[0] += viewWidth - 1;
break;
default:
// Same as left -- do nothing
}
}
/**
* Simulate touching a view and dragging it by the specified amount.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param gravity Which part of the view to use for the initial down event. A combination of
* (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
* @param deltaX Amount to drag horizontally in pixels
* @param deltaY Amount to drag vertically in pixels
*
* @return distance in pixels covered by the drag
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static int dragViewBy(ActivityInstrumentationTestCase test, View v, int gravity,
int deltaX, int deltaY) {
return dragViewBy((InstrumentationTestCase) test, v, gravity, deltaX, deltaY);
}
/**
* Simulate touching a view and dragging it by the specified amount.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param gravity Which part of the view to use for the initial down event. A combination of
* (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
* @param deltaX Amount to drag horizontally in pixels
* @param deltaY Amount to drag vertically in pixels
*
* @return distance in pixels covered by the drag
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static int dragViewBy(InstrumentationTestCase test, View v, int gravity, int deltaX,
int deltaY) {
int[] xy = new int[2];
getStartLocation(v, gravity, xy);
final int fromX = xy[0];
final int fromY = xy[1];
int distance = (int) Math.hypot(deltaX, deltaY);
drag(test, fromX, fromX + deltaX, fromY, fromY + deltaY, distance);
return distance;
}
/**
* Simulate touching a view and dragging it to a specified location.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param gravity Which part of the view to use for the initial down event. A combination of
* (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
* @param toX Final location of the view after dragging
* @param toY Final location of the view after dragging
*
* @return distance in pixels covered by the drag
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static int dragViewTo(ActivityInstrumentationTestCase test, View v, int gravity, int toX,
int toY) {
return dragViewTo((InstrumentationTestCase) test, v, gravity, toX, toY);
}
/**
* Simulate touching a view and dragging it to a specified location.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param gravity Which part of the view to use for the initial down event. A combination of
* (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
* @param toX Final location of the view after dragging
* @param toY Final location of the view after dragging
*
* @return distance in pixels covered by the drag
*/
public static int dragViewTo(InstrumentationTestCase test, View v, int gravity, int toX,
int toY) {
int[] xy = new int[2];
getStartLocation(v, gravity, xy);
final int fromX = xy[0];
final int fromY = xy[1];
int deltaX = fromX - toX;
int deltaY = fromY - toY;
int distance = (int)Math.hypot(deltaX, deltaY);
drag(test, fromX, toX, fromY, toY, distance);
return distance;
}
/**
* Simulate touching a view and dragging it to a specified location. Only moves horizontally.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param gravity Which part of the view to use for the initial down event. A combination of
* (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
* @param toX Final location of the view after dragging
*
* @return distance in pixels covered by the drag
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static int dragViewToX(ActivityInstrumentationTestCase test, View v, int gravity,
int toX) {
return dragViewToX((InstrumentationTestCase) test, v, gravity, toX);
}
/**
* Simulate touching a view and dragging it to a specified location. Only moves horizontally.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param gravity Which part of the view to use for the initial down event. A combination of
* (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
* @param toX Final location of the view after dragging
*
* @return distance in pixels covered by the drag
*/
public static int dragViewToX(InstrumentationTestCase test, View v, int gravity, int toX) {
int[] xy = new int[2];
getStartLocation(v, gravity, xy);
final int fromX = xy[0];
final int fromY = xy[1];
int deltaX = fromX - toX;
drag(test, fromX, toX, fromY, fromY, deltaX);
return deltaX;
}
/**
* Simulate touching a view and dragging it to a specified location. Only moves vertically.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param gravity Which part of the view to use for the initial down event. A combination of
* (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
* @param toY Final location of the view after dragging
*
* @return distance in pixels covered by the drag
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static int dragViewToY(ActivityInstrumentationTestCase test, View v, int gravity,
int toY) {
return dragViewToY((InstrumentationTestCase) test, v, gravity, toY);
}
/**
* Simulate touching a view and dragging it to a specified location. Only moves vertically.
*
* @param test The test case that is being run
* @param v The view that should be dragged
* @param gravity Which part of the view to use for the initial down event. A combination of
* (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
* @param toY Final location of the view after dragging
*
* @return distance in pixels covered by the drag
*/
public static int dragViewToY(InstrumentationTestCase test, View v, int gravity, int toY) {
int[] xy = new int[2];
getStartLocation(v, gravity, xy);
final int fromX = xy[0];
final int fromY = xy[1];
int deltaY = fromY - toY;
drag(test, fromX, fromX, fromY, toY, deltaY);
return deltaY;
}
/**
* Simulate touching a specific location and dragging to a new location.
*
* @param test The test case that is being run
* @param fromX X coordinate of the initial touch, in screen coordinates
* @param toX Xcoordinate of the drag destination, in screen coordinates
* @param fromY X coordinate of the initial touch, in screen coordinates
* @param toY Y coordinate of the drag destination, in screen coordinates
* @param stepCount How many move steps to include in the drag
*
* @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
* {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
* configuring the Activity under test
*/
@Deprecated
public static void drag(ActivityInstrumentationTestCase test, float fromX, float toX,
float fromY, float toY, int stepCount) {
drag((InstrumentationTestCase) test, fromX, toX, fromY, toY, stepCount);
}
/**
* Simulate touching a specific location and dragging to a new location.
*
* @param test The test case that is being run
* @param fromX X coordinate of the initial touch, in screen coordinates
* @param toX Xcoordinate of the drag destination, in screen coordinates
* @param fromY X coordinate of the initial touch, in screen coordinates
* @param toY Y coordinate of the drag destination, in screen coordinates
* @param stepCount How many move steps to include in the drag
*/
public static void drag(InstrumentationTestCase test, float fromX, float toX, float fromY,
float toY, int stepCount) {
Instrumentation inst = test.getInstrumentation();
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
float y = fromY;
float x = fromX;
float yStep = (toY - fromY) / stepCount;
float xStep = (toX - fromX) / stepCount;
MotionEvent event = MotionEvent.obtain(downTime, eventTime,
MotionEvent.ACTION_DOWN, x, y, 0);
inst.sendPointerSync(event);
for (int i = 0; i < stepCount; ++i) {
y += yStep;
x += xStep;
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0);
inst.sendPointerSync(event);
}
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
}
private static class ViewStateSnapshot {
final View mFirst;
final View mLast;
final int mFirstTop;
final int mLastBottom;
final int mChildCount;
private ViewStateSnapshot(ViewGroup viewGroup) {
mChildCount = viewGroup.getChildCount();
if (mChildCount == 0) {
mFirst = mLast = null;
mFirstTop = mLastBottom = Integer.MIN_VALUE;
} else {
mFirst = viewGroup.getChildAt(0);
mLast = viewGroup.getChildAt(mChildCount - 1);
mFirstTop = mFirst.getTop();
mLastBottom = mLast.getBottom();
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final ViewStateSnapshot that = (ViewStateSnapshot) o;
return mFirstTop == that.mFirstTop &&
mLastBottom == that.mLastBottom &&
mFirst == that.mFirst &&
mLast == that.mLast &&
mChildCount == that.mChildCount;
}
@Override
public int hashCode() {
int result = mFirst != null ? mFirst.hashCode() : 0;
result = 31 * result + (mLast != null ? mLast.hashCode() : 0);
result = 31 * result + mFirstTop;
result = 31 * result + mLastBottom;
result = 31 * result + mChildCount;
return result;
}
}
}