我有一个 Android 视图,我正在检测一个投掷手势以执行操作,我想编写一些测试来验证手势是否正常工作。我已经尝试过TouchUtils.dragViewTo
并且TouchUtils.drag
(使用非常少的步骤),但这些似乎都没有触发事件。
有没有办法模拟投掷手势?
我有一个 Android 视图,我正在检测一个投掷手势以执行操作,我想编写一些测试来验证手势是否正常工作。我已经尝试过TouchUtils.dragViewTo
并且TouchUtils.drag
(使用非常少的步骤),但这些似乎都没有触发事件。
有没有办法模拟投掷手势?
好的,这是一个非常老的问题,但是发布一个对我有用的解决方案,可能会帮助其他来寻找这个的人
int[] xy = new int[2];
View v = currentActivity.getCurrentFocus();
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);
int screenWidth = currentActivity.getWindowManager().getDefaultDisplay().getWidth();
//Drag from centre of screen to Leftmost edge of display
TouchUtils.drag(this, (screenWidth - 1), x, fromY, fromY , 5); //Vary the last parameter to sdjust speed of fling
通过查看 TouchUtils 源,这里的问题是步数只是要生成的触摸事件的数量,并不影响它们发生的速度:
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);
inst.waitForIdleSync();
}
每次事件后,它都在等待与应用程序同步,所以看起来这种情况发生的速度不够快,无法一发不可收拾。我们可以从 GestureDetector 如何识别一个 fling 中看出:
// A fling must travel the minimum tap distance
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000);
final float velocityY = velocityTracker.getYVelocity();
final float velocityX = velocityTracker.getXVelocity();
if ((Math.abs(velocityY) > ViewConfiguration.getMinimumFlingVelocity())
|| (Math.abs(velocityX) > ViewConfiguration.getMinimumFlingVelocity())){
handled = mListener.onFling(mCurrentDownEvent, mCurrentUpEvent, velocityX, velocityY);
}
所以我推荐一种自定义的拖动方法,它不等待每次触摸移动事件的同步(无论如何,我们并不关心 UI 是否随着每次拖动移动而更新,我们只想生成一个弹跳)。像这样的东西(未经测试):
public static void fling(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, fromX, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
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);
//inst.waitForIdleSync();
}
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, fromX, y, 0);
inst.sendPointerSync(event);
inst.waitForIdleSync();
}
好吧,实际上我所做的只是在运动事件循环中注释掉等待空闲同步。为行进距离和步数选择一些合理的值,这应该可行。如果没有,您可能需要在循环中短暂等待,以便在事件来得太快时稍微隔开事件。
不确定这是否是您要查找的内容,但这是我编写的一个测试示例,以确保投掷手势在自定义图库组件上起作用。
public void testLeftSwipe() {
int initialSelectedItemPosition = mGallery.getSelectedItemPosition();
Rect r = new Rect();
mGallery.getGlobalVisibleRect(r);
float fromX = r.centerX();
float toX = r.centerX() - (r.width() / 4);
float fromY = r.centerY();
float toY = r.centerY();
int stepCount = 10;
TouchUtils.drag(this, fromX, toX, fromY, toY, stepCount);
assertTrue(mGallery.getSelectedItemPosition() > initialSelectedItemPosition);
}