2010-10-22 23 views
6

Tengo una vista de Android en la que estoy detectando un gesto arrojado para realizar una operación, y quiero escribir algunas pruebas para verificar que el gesto funciona correctamente. He intentado TouchUtils.dragViewTo y TouchUtils.drag (con un número muy pequeño de pasos) pero ninguno de estos parece desencadenar el evento.Simular un gesto fling en Android ActivityInstrumentationTestCase2

¿Hay alguna forma de simular el gesto arrojado?

+1

¿no es entonces probar las cosas mal? Lo que le gustaría probar es la acción que se realiza cuando se produce el gesto de arrojar. Supongo que el gesto arrojado es solo un evento simple con un oyente de evento adjunto. Dentro del oyente del evento, probablemente invoque alguna función, y esa es esa función que le gustaría probar. – Nailuj

+0

Ya estoy probando la función de salida, pero quiero saber que funciona correctamente con el gesto fling, ya que importa en qué dirección ocurre el gesto y quiero probar la lógica de eso, ya que el oyente interpreta la dirección de la aventura. Parece extraño que pueda interactuar con la vista simulando tocar y arrastrar, pero ninguna de las operaciones de arrastre parece realizar una aventura. Me pregunto si me estoy perdiendo algo sutil – Kevin

+1

Ok, ya veo. Ahora bien, esto es solo que estoy pensando en voz alta (y no estoy muy familiarizado con las pruebas en Android, por lo que podría haber problemas que no veo con este enfoque), pero si quieres probar la lógica de interpretar el gesto, no podría ¿Acabas de poner otra capa de abstracción? En su manejador de eventos 'onFling', simplemente pasa todos los argumentos a su propia función' processFlingEvent (MotionEvent, MotionEvent, float, float) ', ¿cuál debería ser más fácil de probar? – Nailuj

Respuesta

0

De su análisis de la fuente TouchUtils, el problema aquí es que el número de pasos es sólo el número de eventos de toque para generar y no afecta a la rapidez con que se planteen:

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

Está esperando para una sincronización con la aplicación después de cada evento, por lo que no parece que eso ocurra lo suficientemente rápido como para lanzarse. Podemos ver que a partir de la forma en la GestureDetector reconoce una aventura:

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

por lo que recomiendo un método personalizado de arrastre que no espera a que se sincroniza en cada evento movimiento táctil (no nos importa que las actualizaciones de la interfaz de usuario con cada uno arrastrar mover de todos modos, solo queremos generar una aventura). Algo como esto (no probado):

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

Bueno, en realidad todo lo que hice no había comente la espera de sincronización de inactividad en el bucle de eventos de movimiento. Elija algunos valores razonables para la distancia recorrida y el recuento de pasos, y eso debería funcionar. Si no es así, es posible que necesites una pequeña espera en el ciclo para espaciar ligeramente los eventos si van demasiado rápido.

0

no estoy seguro de si esto es lo que estás buscando, pero aquí hay un ejemplo de una prueba que escribí para asegurarte de que el gesto fling funciona en un componente de galería personalizado.

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

Ok, esta es una pregunta muy viejo, pero publicar una solución que funcionó para mí, puede ayudar a otros que vienen en busca de este

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