2010-08-24 14 views
7

Soy bastante nuevo en el desarrollo de aplicaciones de Android, y he estado jugando con gestos de deslizamiento con SimpleOnGestureListener y ViewFlipper de Android. Hay 3 hijos de ViewFlipper, y cada uno es ScrollView. Todos se rellenan dinámicamente cuando se carga la actividad, y no cambian después de eso. ScrollView es donde se adjuntan los SimpleOnGestureListeners.Scrollview no se desliza cuando es demasiado corto para desplazarse

Aquí está el diseño que estoy usando:
+ ViewFlipper
++ ScrollView (x3, uno para cada página, cada uno con el siguiente :)
+++ LinearLayout (vertical)
++++ Vista de Texto
++++ TableLayout (dinámicamente poblada w/TableRows)
++++ Ver

me extendió el método onFling con el código común tutorial se puede encontrar en cualquier lugar en línea, y funciona muy bien - excepto cuando uno de los ScrollViews no contiene suficiente contenido para scrol l.

Reduje el problema a la detección táctil anulando y llamando súper a cada uno de los métodos de SimpleOnGestureListener para agregar una impresión al registro.

Cuando deslizo una página que se desplaza, obtengo algo lleno de "en onClick" "onScroll" "en onFling", etc. En una página que es demasiado corta para desplazarme, aparece "en onClick" "enShowPress "" en onLongPress ", y eso solo si estoy tocando el contenido dentro de los hijos de la vista de desplazamiento demasiado cortos: si toco en otro lugar, no obtengo ningún evento.

Ideas sobre qué es lo que está mal, o cómo detectar el gesto de deslizamiento sin importar qué tan grande sea ScrollView?

EDIT: he determinado que cuando ejecuto esto en un emulador de Android 2.2, en comparación con el emulador de Android 2.1u1 DroidX que he estado usando, desaparece. Esto es reproducible en múltiples entornos.


Tengo más información sobre esto; parece que onInterceptTouchEvent no se llama para cada evento de movimiento cuando una vista de desplazamiento está contenida dentro de una aleta (o un WorkspaceView).

En particular, el comportamiento que encontré mientras se modificaba otra clase de vista para solucionar este mismo asunto (que no es exclusivo de las aletas) fue el siguiente - en cuenta que este es Android 2.1 solamente:

Si el ScrollView es lo suficientemente largo para desplazarse, el evento de movimiento ACTION_DOWN es capturado por el ScrollView, y cada evento ACTION_MOVE subsiguiente pasa por el evento InterceptTouch del flipper, donde es interceptado y manejado apropiadamente. En Android 2.2, este comportamiento ocurre independientemente de la longitud de desplazamiento.

Volver a 2,1: Si el ScrollView no es lo suficientemente largo para desplazarse, el evento de movimiento ACTION_DOWN es no ha caído en la ScrollView, sino que regresa a la onTouchEvent de la aleta. Todos los sucesos ACTION_MOVE subsiguientes del mismo gesto omiten la función onInterceptTouchEvent y van directamente a la función onTouchEvent.

La forma en que resolví esto fue tomar la funcionalidad que tenía en onTouchEvent para eventos ACTION_MOVE y refactorizarla en su propio método. De esta forma, puedo tener la llamada aTouchEvent onInceptceptTouchEvent seguida de esa funcionalidad si detecta que el evento no se ha manejado previamente.

case MotionEvent.ACTION_MOVE: 

       if (touchState == TOUCH_STATE_SCROLLING) { 
        handleScrollMove(ev); 
       } else { 
    //    Log.d("workspace","caught a move touch event but not scrolling"); 
        //NOTE: We will never hit this case in Android 2.2. This is to fix a 2.1 bug. 
        //We need to do the work of interceptTouchEvent here because we don't intercept the move 
        //on children who don't scroll. 

        Log.d("workspace","handling move from onTouch"); 

        if(onInterceptTouchEvent(ev) && touchState == TOUCH_STATE_SCROLLING){ 
         handleScrollMove(ev); 
        } 

       } 

       break; 

Esto es de WorkspaceView.java (una modificación de Workspace.java de Android, que se encuentra en el proyecto Andro-vistas en Google Code, y ahora aquí: Horizontal "tab"ish scroll between views). En el caso de que recibamos un evento de movimiento, y estamos desplazándonos (lo cual solo ocurre si deliberadamente elegimos interceptarlo, es decir, está configurado en la función de intercepción, entonces ya hemos estado en la función de interceptar) que llevamos a cabo el comportamiento de movimiento que deseamos. Si recibimos un evento de movimiento aquí y no estamos desplazándonos, luego enviamos el evento nuevamente a través de Interceptar, y luego vemos si estamos listos para desplazarnos. Si es así, llevamos a cabo la acción.

No es elegante, pero funciona!

Respuesta

7

que necesitaba para crear una nueva clase que se extendía ScrollView, y se utiliza la siguiente:.

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    super.onTouchEvent(event); 
    return gestureDetector.onTouchEvent(event); 
} 

@Override 
public boolean dispatchTouchEvent(MotionEvent ev){ 
    gestureDetector.onTouchEvent(ev); 
    super.dispatchTouchEvent(ev); 
    return true; 
} 

no tengo ni idea de por qué, pero si tratar de devolver cualquier cosa menos cierto en dispatchTouchEvent (lo lógico habría sido

return (gestureDetector.onTouchEvent(ev) || super.dispatchTouchEvent(ev)); 

si entiendo correctamente), no funciona, y esto lo hace.

1

Pruebe la configuración android:fillViewport="true" en su diseño xml para cada uno de los ScrollView s. Esto le indica al ScrollView a ser tan grande como la vista que está contenida en

+0

Se establece como tal en todos los niños. Incluso copié directamente y pegué el xml en http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+PlanetAndroidCom+(Planet+Android) y lo intenté como una vista infantil. Después de tocar un poco me las arreglé para hacer que todos llenaran la ventana gráfica. Pero no hubo suerte en la devolución de llamada incluso una vez que lo hicieron. Hasta ahora, no scrollbar = no onFling. –

Cuestiones relacionadas