2011-01-25 15 views
20

Tengo un HorizontalScrollView que contiene un RelativeLayout. Este diseño está vacío en el XML y está poblado de java en onCreate.Cómo desplazarse mediante programación un HorizontalScrollView

Me gustaría que esta vista de desplazamiento esté inicialmente en algún lugar en medio del RelativeLayout, que es mucho más grande que la pantalla.

Intenté mHorizScrollView.scrollTo(offsetX, 0); que no funciona. No sé lo que está mal con esto.

Podría publicar el código, pero no es realmente relevante. Lo que importa es que todo se hace programáticamente (tiene que: s), y que la posición inicial del HorizontalScrollView debe establecerse mediante programación.

Gracias por leer. Por favor dígame si necesita más detalles o si esto no es lo suficientemente claro.

Respuesta

24

He encontrado que si extend la HorizontalScrollView y anular el onLayout, se limpia puede desplazarse, después de la llamada súper a onLayout:

MyScrollView extends HorizontalScrollView { 
    protected void onLayout (boolean changed, int l, int t, int r, int b) { 
     super.onLayout(changed, l, t, r, b); 
     this.scrollTo(wherever, 0); 
    } 
} 

EDIT: Para desplazarse a inicio o final puede usar:

this.fullScroll(HorizontalScrollView.FOCUS_RIGHT/FOCUS_LEFT); 

en lugar de

this.scrollTo(wherever, 0); 
0

La función scrollTo debería funcionar. ¿Cuál es el layout_width del HSV y la vista dentro de él?

+1

Creo que este es un problema de tiempo. Las vistas dentro del HSV se agregan en el tiempo de ejecución (desde onCreate) y el layout_width del HSV es fill_parent. El mHSV.scrollTo() se llama desde onStart. –

15

Para probar si se trata de un problema de temporización (que creo que es), en lugar de llamar a scrollTo() en onStart, llame a postDelayed() con un Runnable que invoca scrollTo, con un retraso de 30 o más.

+1

Esto confirmó que es, de hecho, un problema de tiempo. ¿Hay una manera más limpia de hacer esto, que un Runnable postDelayed? –

+1

Probablemente podría subclasificar HorizontalScrollView, agregar un campo que indique que es necesario desplazarse, y luego hacer el desplazamiento al final de la siguiente llamada a onLayout() (o tal vez en computeScroll() o algún otro método). Creo que usar postDelayed es simplemente más fácil. –

+0

Derecha. Gracias de nuevo. –

1

El problema es que la vista todavía no tiene un tamaño. La forma Limpia de hacer esto es implementar onSizeChanged de ScrollView para enviar un mensaje a un Manejador en su actividad a fin de notificar a la actividad que la vista tiene un tamaño y que es posible desplazarse.

+0

Esto se veía realmente bien pero no funciona. Creé una clase que amplía HorizontalScrollView y que implementa onSizeChanged. Cuando se llama a esta devolución de llamada, llama a un método en la actividad que realiza el desplazamiento. Sin embargo, el desplazamiento no funciona. Solo funciona si se retrasa. –

0

La función onSizeChanged debería funcionar. Lo que no comprende es que onSizeChanged debe enviar un mensaje a un Manejador de su actividad y no a ninguna función de devolución de llamada, porque un controlador ejecutará el código en el hilo de la interfaz de usuario. No puedes hacer operaciones de UI fuera de él. Eche un vistazo a los controladores.

+1

onSizeChanged debe invocarse en el hilo de la interfaz de usuario porque cuando llamé a scrollTo desde onSizeChanged, no se quejó. –

1

Use view.post y escriba scrollTo (x, y) dentro del método de ejecución. Esta es la forma de invalidar la vista en el método de publicación según el documento API de Android.

+0

Acabo de reemplazar mi publicación Dejado con un .post y funciona como un amuleto. Tan robusto como un oyente a medida que se desencadena _después_, la vista se ha adjuntado. Lo uso para acceder a las dimensiones de una vista, ya que solo está disponible después de que se haya adjuntado a la pantalla y medido. – slott

9

Un mejor enfoque sería usar el ViewTreeObserver para observar los diseños.

View interestedInView; 
onCreate(){ 
    //Code 

    //Observe for a layout change 
    ViewTreeObserver viewTreeObserver = interestedInView.getViewTreeObserver(); 
    if (viewTreeObserver.isAlive()) { 
    viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
     //REMOVE THE VIEWTREE OBSERVER 
     //interestedInView is ready for size and position queries because it has been laid out 
     } 
    }); 
    } 
} 
+0

Gracias por ayudarme a trabajar para mí, pero tengo una pregunta ¿requiere más procesamiento y luego se demora? (Nuevo Runnable() ....) – MGD

+1

Bueno, si está tomando sobrecarga en tiempo de ejecución, la respuesta es sí, porque está agregando un nuevo oyente y quitándolo entonces. Pero es tan mínimo que no contará. Y vale la solidez del enfoque. –

+0

Ahora estoy usando ViewTreeObserver y funciona para mí, por favor dígame si es menos eficiente o qué ??? – MGD

22
public void autoSmoothScroll() { 

     final HorizontalScrollView hsv = (HorizontalScrollView) view.findViewById(R.id.horiscroll); 
     hsv.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       //hsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT); 
       hsv.smoothScrollBy(500, 0); 
      } 
     },100); 
    } 
Cuestiones relacionadas