HorizontalScrollView: desplazamiento automático para finalizar cuando se agregan nuevas vistas?
Tengo un HorizontalScrollView que contiene un LinearLayout. En la pantalla tengo un botón que agregará nuevas vistas a LinearLayout en tiempo de ejecución, y me gustaría que la vista de desplazamiento para desplazarse hasta el final de la lista cuando se agrega una nueva vista.
Casi lo tengo trabajando – excepto que siempre se desplaza una vista de la última vista. Parece que se está desplazando sin calcular primero la inclusión de la nueva vista.
- Disposición de interfaz de usuario de dos pasos: ¿Por qué?
- Espresso - Juego SeekBar
- Ventaja de ListFragment sobre un ListView o Fragmento normal
- Cómo arreglar este código todas las pantallas de Android
- ¿Cómo se ve un Android StackView?
En mi aplicación estoy usando un objeto de vista personalizado, pero he hecho una pequeña aplicación de prueba que utiliza ImageView y tiene el mismo síntoma. He intentado varias cosas como requestLayout () en el Layout y ScrollView, he intentado scrollTo (Integer.MAX_VALUE) y se desplazó en el netherverse 🙂 ¿Estoy violando un problema de hilo de interfaz de usuario o algo así?
- Almiar
======
public class Main extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button b = (Button) findViewById(R.id.addButton); b.setOnClickListener(new AddListener()); add(); } private void add() { LinearLayout l = (LinearLayout) findViewById(R.id.list); HorizontalScrollView s = (HorizontalScrollView) findViewById(R.id.scroller); ImageView i = new ImageView(getApplicationContext()); i.setImageResource(android.R.drawable.btn_star_big_on); l.addView(i); s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } private class AddListener implements View.OnClickListener { @Override public void onClick(View v) { add(); } } }
Diseño XML:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <HorizontalScrollView android:id="@+id/scroller" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scrollbarSize="50px"> <LinearLayout android:id="@+id/list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="4px"/> </HorizontalScrollView> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center"> <Button android:id="@+id/addButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingLeft="80px" android:paddingRight="80px" android:paddingTop="40px" android:paddingBottom="40px" android:text="Add"/> </LinearLayout> </LinearLayout>
- Cómo ocultar / mostrar el botón en el widget de pantalla de inicio de Android
- IOS-como herramienta de guión gráfico para el proyecto de Android?
- Hacer el diseño lineal seleccionable como un elemento de lista en una vista de lista (Android)
- Latch (usado para esperar la respuesta asíncrona) congela el WebView (y la interfaz de usuario)
- Cómo crear GUI en Android en lugar de utilizar XML?
- Cambiar el lado que aparece el texto en un botón de opción
- Desaparecer divisor en ListView cuando ArrayAdapter.isEnabled devuelve false
- Biblioteca de vista o fragmento para componer la interfaz de usuario para tipos de datos comunes
Creo que hay un problema de tiempo. El diseño no se realiza cuando se agrega una vista. Se solicita y se hace poco tiempo después. Cuando llame a fullScroll inmediatamente después de agregar la vista, el ancho de la linea lineal no ha tenido la oportunidad de expandirse.
Prueba a sustituir:
s.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
con:
s.postDelayed(new Runnable() { public void run() { s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } }, 100L);
El corto retraso debe dar al sistema suficiente tiempo para asentarse.
PS Puede ser suficiente simplemente retrasar el desplazamiento hasta después de la iteración actual del bucle de interfaz de usuario. No he probado esta teoría, pero si es correcto, sería suficiente hacer lo siguiente:
s.post(new Runnable() { public void run() { s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } });
Me gusta esto mejor porque la introducción de un retraso arbitrario parece hacky para mí (a pesar de que era mi sugerencia).
Sólo otra sugerencia, ya que esta pregunta me ayudó mucho :).
Usted puede poner un oyente cuando la vista ha terminado su fase de diseño, y justo después de hacer el fullScroll althought necesitará ampliar la clase para eso.
Sólo hice esto porque quería desplazarme a una sección justo después de onCreate () para evitar que parpadee desde el punto de partida hasta el punto de desplazamiento.
Algo como:
public class PagerView extends HorizontalScrollView { private OnLayoutListener mListener; ///... private interface OnLayoutListener { void onLayout(); } public void fullScrollOnLayout(final int direction) { mListener = new OnLayoutListener() { @Override public void onLayout() { fullScroll(direction) mListener = null; } }; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if(mListener != null) mListener.onLayout(); } }
Estoy de acuerdo con @monxalo y @ granko87 que el mejor enfoque es con un oyente en lugar de hacer una suposición de que el diseño será completa si dejamos pasar una cantidad arbitraria de tiempo.
En caso de que, al igual que yo, no necesite usar una subclase horizontalScrollView personalizada, sólo puede agregar un OnLayoutChangeListener para mantener las cosas simples:
mTagsScroller.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { mTagsScroller.removeOnLayoutChangeListener(this); mTagsScroller.fullScroll(View.FOCUS_RIGHT); } });
Utilice el método View smoothScrollTo
postDelayed(new Runnable() { public void run() { scrollView.smoothScrollTo(newView.getLeft(), newView.getTop()); } }, 100L);
Usted necesita poner en un runnable así que usted da tiempo al proceso de la disposición para colocar la nueva visión
Esto es lo que hice.
//Observe for a layout change ViewTreeObserver viewTreeObserver = yourLayout.getViewTreeObserver(); if (viewTreeObserver.isAlive()) { viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { yourHorizontalScrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } }); }
Creo que el mejor enfoque es el publicado por monxalo porque no se puede saber cuánto tiempo se tarda hasta que el diseño se hace. Lo intenté y funciona perfectamente. La única diferencia es que agregé sólo una fila a mi vista de desplazamiento horizontal personalizada:
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); this.fullScroll(HorizontalScrollView.FOCUS_RIGHT); }
Utilice debajo del código para desplazamiento horizontal { Desplácese a la derecha }
view.post(new Runnable() { @Override public void run() { ((HorizontalScrollView) Iview .findViewById(R.id.hr_scroll)) .fullScroll(HorizontalScrollView.FOCUS_RIGHT); } });
- El método setMobileDataEnabled ya no se puede llamar desde Android L y después
- ¿Cómo solucionarlo? El código de la versión de su APK debe ser superior a 2. "en la Consola para desarrolladores de Google Play.