2010-10-22 77 views
6

我有一个Android视图,我正在检测执行操作的手势,并且我想写一些测试来验证手势是否正常工作。我试过TouchUtils.dragViewToTouchUtils.drag(只有很少的几个步骤),但这些都没有触发事件。模拟Android中的一个手势动作ActivityInstrumentationTestCase2

有没有一种方法来模拟扔手势?

+1

你不是那么测试错误的事情?你会喜欢测试什么,是在发生抛出手势时执行的操作。我认为扔手势只是一个简单的事件,附带一个事件监听器。在事件监听器内部,你可能会调用一些函数 - 它是_that_函数,你想测试。 – Nailuj 2010-10-22 11:29:04

+0

我已经在测试输出函数,但是我想知道它是否正确地执行了这个手势,因为它关系到手势发生在哪个方向,我想测试一下这个逻辑,因为这个监听器解释了这个投掷方向。看起来很奇怪,我可以通过模拟触摸和拖拽来与视图​​进行交互,但是没有一个拖动操作看起来像是在执行一些动作。我只是想知道我是否错过了一些微妙的东西 – Kevin 2010-10-22 12:41:53

+1

好的,我明白了。现在,这只是我的想法而已(我对Android测试不太熟悉,所以可能会遇到我没有看到的方法),但是如果您想测试解释手势的逻辑,你只是把另一层抽象?在你的'onFling'事件处理程序中,你只需将所有参数传递给你自己的'processFlingEvent(MotionEvent,MotionEvent,float,float)'函数,然后应该更容易测试? – Nailuj 2010-10-22 12:56:55

回答

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

嗯,其实我所做的有注释掉等待在运动事件循环空闲同步。为距离行程和步数选择一些合理的值,这应该起作用。如果没有,您可能需要在循环中稍稍等待,以便在事件发生太快时稍微隔开这些事件。

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