在Android ActivityInstrumentationTestCase2中模拟一个fling手势

时间:2010-10-22 11:00:15

标签: android android-2.2-froyo

我有一个Android视图,我正在检测执行操作的手势,我想编写一些测试来验证手势是否正常工作。我尝试了TouchUtils.dragViewToTouchUtils.drag(步数非常少),但这些都没有触发事件。

有没有办法模拟这种投掷手势?

3 个答案:

答案 0 :(得分:2)

好的,这是一个非常古老的问题,但是发布一个对我有用的解决方案可能有助于其他人来寻找这个

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

答案 1 :(得分:0)

通过查看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如何识别出一个东西:

           // 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();
}

嗯,实际上我在那里所做的就是在运动事件循环中注释等待空闲同步。为行程距离和步数选择一些合理的值,这应该有效。如果没有,您可能需要在循环中进行短暂的等待,以便在事件过快时稍微分开。

答案 2 :(得分:0)

不确定这是否是您所寻找的,但这里是我编写的一个测试示例,以确保该手势在自定义图库组件上运行。

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);
}