Scrollview no desliza cuando es demasiado corto para desplazarse

Soy bastante nuevo en el desarrollo de aplicaciones para Android, y he estado jugando con gestos de deslizamiento usando SimpleOnGestureListener de Android y ViewFlipper. Hay 3 hijos del ViewFlipper, y cada uno es un ScrollView. Todos ellos están dinámicamente poblados cuando la actividad se carga, y no cambian después de eso. El ScrollView es donde se adjuntan los SimpleOnGestureListeners.

Aquí está el diseño que estoy usando:
+ ViewFlipper
++ ScrollView (x3, uno para cada página, cada uno con lo siguiente 🙂
+++ LinearLayout (vertical)
++++ TextView
++++ TableLayout (dinámicamente poblado con TableRows)
++++ Ver

He extendido el método onFling con el código tutorial común que puede encontrar en cualquier lugar en línea, y funciona muy bien – excepto cuando uno de los ScrollViews no contiene suficiente contenido para desplazarse.

He reducido el problema a la detección de toque mediante la sustitución y la llamada de super en cada uno de los métodos de SimpleOnGestureListener para agregar un print-to-log.

Cuando hago un desplazamiento en una página que se desplaza, obtengo algo lleno de "in onClick", "onScroll", "onFling", etc. En una página que es demasiado corta para desplazarse, obtengo "on onClick" en onShowPress en onLongPress ", Y eso es sólo si toco el contenido dentro de los niños de los scrollview demasiado cortos, si toco a otro lugar no tengo ningún evento en absoluto.

Ideas sobre lo que está mal, o cómo detectar el gesto de deslizamiento no importa cuán grande es el ScrollView?

EDIT: He determinado que cuando ejecuto esto en un emulador de Android 2.2, a diferencia del emulador de Android 2.1u1 DroidX que he estado usando, se va. 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 una vista de espacio de trabajo).

En particular, el comportamiento que encontré al modificar otra clase de vista para arreglar este mismo problema (no es exclusivo de las aletas) fue el siguiente: tenga en cuenta que sólo es Android 2.1:

Si la vista de desplazamiento es lo suficientemente larga como para desplazarse, el evento de movimiento ACTION_DOWN es capturado por ScrollView, y cada evento ACTION_MOVE siguiente pasa a través deInterceptTouchEvent de la aleta, donde es interceptado y manejado apropiadamente. En android 2.2, este comportamiento ocurre independientemente de la longitud de desplazamiento.

Regresar a 2.1: Si la vista de desplazamiento no es lo suficientemente larga como para desplazarse, el evento de movimiento ACTION_DOWN no queda atrapado en la vista de desplazamiento, sino que vuelve al evento onTouch de la aleta. Todos los eventos ACTION_MOVE posteriores del mismo gesto saltaron la función onInterceptTouchEvent y ir directamente a la función onTouchEvent!

La forma en que resolví esto era tomar la funcionalidad que tenía en eventos onTouchEvent para ACTION_MOVE y refactorizarlo en su propio método. De esta manera, puedo tener onTouchEvent llamada onInterceptTouchEvent seguida por esa funcionalidad si detecta que el evento ha pasado anteriormente sin tratamiento.

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-views en el código de google, y ahora aquí: Horizontal "tab" ish desplazarse entre las vistas ). En el caso de que recibamos un evento de movimiento, y estamos desplazando (lo que sólo sucede si hemos elegido deliberadamente para interceptarlo – es decir, se establece en la función de intercepción, por lo que hemos estado en la función de intercepción ya) que realizamos El comportamiento de movimiento que deseamos. Si recibimos un evento de movimiento aquí y no estamos desplazándonos, enviamos el evento de nuevo a través de onIntercept, y luego veremos si ahora estamos configurados para desplazarnos. Si es así, realizamos la acción.

No es elegante, pero funciona!

Necesitaba crear una nueva clase que ampliara ScrollView, y utilizó esto:

 @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 intento devolver algo pero cierto en dispatchTouchEvent (lo lógico habría sido

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

Si lo entiendo correctamente), no funciona, y esto sí.

Intenta establecer android:fillViewport="true" en tu layout xml para cada ScrollView . Eso le dice al ScrollView que sea tan grande como la vista que contiene.

  • Android captura todos los eventos de movimiento y los envía a los niños
  • Error de cursor Android: "asegúrese de que el cursor se inicialice correctamente antes de acceder a los datos de él ..."
  • Android ViewFlipper + animación de pantalla de inicio
  • Android - inAnimation funciona para ViewFlipper pero outAnimation no
  • Cómo cambiar entre actividades con viewflipper
  • Android: Flip Animation utilizando XML para animación en android
  • Creación de un ViewFlipper como la pantalla de inicio con MotionEvent.ACTION_MOVE
  • Implementación del transformador de página de alejamiento de Android para un ViewFlipper
  • Android: ViewFlipper o ViewPager - ¿Cuál es la mejor opción?
  • Cómo inflar correctamente un diseño con un ViewFlipper anidado?
  • ViewPager con límites de páginas anteriores y siguientes
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.