Tengo mucho tiempo para ListView
que el usuario pueda desplazarse antes de volver a la pantalla anterior. Cuando el usuario abre esto ListView
nuevamente, quiero que la lista se desplace al mismo punto en el que se encontraba anteriormente. ¿Alguna idea sobre cómo lograr esto?
android
android-listview
scroll
scroll-position
rantravee
fuente
fuente
Respuestas:
Prueba esto:
Explicación:
ListView.getFirstVisiblePosition()
devuelve el elemento de la lista visible superior. Pero este elemento se puede desplazar parcialmente fuera de la vista, y si desea restaurar la posición exacta de desplazamiento de la lista, necesita obtener este desplazamiento. Por lo tanto,ListView.getChildAt(0)
devuelve elView
para el elemento de la lista superior y luegoView.getTop() - mList.getPaddingTop()
devuelve su desplazamiento relativo desde la parte superior delListView
. Luego, para restaurar laListView
posición de desplazamiento del 's, llamamosListView.setSelectionFromTop()
con el índice del elemento que queremos y un desplazamiento para colocar su borde superior desde la parte superior delListView
.fuente
int index = mList.getFirstVisiblePosition();
y sólo una línea para restaurar:mList.setSelectionFromTop(index, 0);
. Gran respuesta sin embargo (+1)! He estado buscando una solución elegante a este problema.fuente
Adopté la solución sugerida por @ (Kirk Woll), y funciona para mí. También he visto en el código fuente de Android para la aplicación "Contactos", que utilizan una técnica similar. Me gustaría agregar más detalles: en la parte superior de mi clase derivada de ListActivity:
Entonces, algunos métodos anulan:
Por supuesto, "loadData" es mi función para recuperar datos de la base de datos y ponerlos en la lista.
En mi dispositivo Froyo, esto funciona tanto cuando cambias la orientación del teléfono como cuando editas un elemento y vuelves a la lista.
fuente
mListState = getListView().onSaveInstanceState().
Principalmente en la rotación del dispositivo.onRestoreInstanceState
nunca se llama :(Una forma muy simple:
El método setSelection restablecerá la lista al elemento suministrado. Si no está en modo táctil, el elemento se seleccionará realmente si en modo táctil solo se colocará en la pantalla.
Un enfoque más complicado:
fuente
Encontré algo interesante sobre esto.
Intenté setSelection y scrolltoXY pero no funcionó en absoluto, la lista permaneció en la misma posición, después de una prueba y error obtuve el siguiente código que funciona
Si en lugar de publicar el Runnable intenta ejecutar runOnUiThread, tampoco funciona (al menos en algunos dispositivos)
Esta es una solución muy extraña para algo que debería ser sencillo.
fuente
setSelectionFromTop()
no funciona¡¡PRECAUCIÓN!! Hay un error en AbsListView que no permite que onSaveState () funcione correctamente si ListView.getFirstVisiblePosition () es 0.
Entonces, si tiene imágenes grandes que ocupan la mayor parte de la pantalla y se desplaza a la segunda imagen, pero se muestra un poco de la primera, la posición de desplazamiento no se guardará ...
de AbsListView.java:1650 (comentarios míos)
Pero en esta situación, la 'parte superior' en el código a continuación será un número negativo que causa otros problemas que impiden que el estado se restaure correctamente. Entonces, cuando el 'top' es negativo, obtenga el próximo hijo
fuente
Eso es suficiente
fuente
Para algunos que buscan una solución a este problema, la raíz del problema puede ser dónde está configurando su adaptador de vistas de lista. Después de configurar el adaptador en la vista de lista, restablece la posición de desplazamiento. Solo algo a tener en cuenta. Moví la configuración del adaptador en mi onCreateView después de que tomamos la referencia a la vista de lista, y me resolvió el problema. =)
fuente
Estoy publicando esto porque me sorprende que nadie haya mencionado esto.
Después de que el usuario haga clic en el botón Atrás, volverá a la vista de lista en el mismo estado en que salió de ella.
Este código anulará el botón "arriba" para comportarse de la misma manera que el botón Atrás, por lo que en el caso de Vista de lista -> Detalles -> Volver a vista de lista (y ninguna otra opción) este es el código más simple para mantener la posición de desplazamiento y el contenido en la vista de lista.
Precaución: si puede ir a otra actividad desde la actividad de detalles, el botón arriba lo regresará a esa actividad, por lo que tendrá que manipular el historial del botón de retroceso para que esto funcione.
fuente
¿No es suficiente
android:saveEnabled="true"
en la declaración xml ListView suficiente?fuente
LA MEJOR SOLUCIÓN ES:
DEBE LLAMAR EN POST Y EN HILO!
fuente
Puede mantener el estado de desplazamiento después de una recarga si guarda el estado antes de volver a cargarlo y restaurarlo después. En mi caso, hice una solicitud de red asincrónica y volví a cargar la lista en una devolución de llamada después de que se completara. Aquí es donde restauro el estado. El ejemplo de código es Kotlin.
fuente
Si está utilizando fragmentos alojados en una actividad, puede hacer algo como esto:
fuente
Si está guardando / restaurando la posición de desplazamiento de
ListView
usted mismo, básicamente está duplicando la funcionalidad ya implementada en el marco de Android. LaListView
posición de desplazamiento fina restauraciones simplemente bien por sí sola excepción de una advertencia: como @aaronvargas mencionan que hay un error en elAbsListView
que no va a dejar que para restaurar la posición de desplazamiento bien para el primer elemento de la lista. Sin embargo, la mejor manera de restaurar la posición de desplazamiento es no restaurarla. El marco de Android lo hará mejor para ti. Solo asegúrese de cumplir con las siguientes condiciones:setSaveEnabled(false)
método y no haber establecido elandroid:saveEnabled="false"
atributo para la lista en el archivo de diseño xmlExpandableListView
anulaciónlong getCombinedChildId(long groupId, long childId)
para que devuelva un número largo positivo (la implementación predeterminada en la claseBaseExpandableListAdapter
devuelve un número negativo). Aquí hay ejemplos:.
ListView
oExpandableListView
se usa en un fragmento, no vuelva a crear el fragmento en la recreación de la actividad (después de la rotación de la pantalla, por ejemplo). Obtenga el fragmento con elfindFragmentByTag(String tag)
método.ListView
tiene unandroid:id
y es único.Para evitar la advertencia mencionada anteriormente con el primer elemento de la lista, puede diseñar su adaptador de la forma en que devuelve una vista simulada especial de altura de cero píxeles para la
ListView
posición 0. Aquí está el ejemplo simple que el proyecto muestraListView
yExpandableListView
restaura sus posiciones de desplazamiento fino, mientras que sus posiciones de desplazamiento no se guardan explícitamente / restaurado La posición de desplazamiento fino se restaura perfectamente incluso para los escenarios complejos con cambio temporal a alguna otra aplicación, rotación de doble pantalla y cambio a la aplicación de prueba. Tenga en cuenta que si sale explícitamente de la aplicación (presionando el botón Atrás), la posición de desplazamiento no se guardará (así como todas las demás Vistas no guardarán su estado). https://github.com/voromto/RestoreScrollPosition/releasesfuente
Para una actividad derivada de ListActivity que implementa LoaderManager.LoaderCallbacks usando un SimpleCursorAdapter, no funcionó para restaurar la posición en onReset (), porque la actividad casi siempre se reiniciaba y el adaptador se recargaba cuando se cerraba la vista de detalles. El truco consistía en restaurar la posición en onLoadFinished ():
en onListItemClick ():
en onLoadFinished ():
en onBackPressed ():
fuente
Ninguna de las soluciones ofrecidas aquí parecía funcionar para mí. En mi caso, tengo un
ListView
enFragment
que estoy reemplazando en unFragmentTransaction
, por lo queFragment
se crea una nueva instancia cada vez que se muestra el fragmento, lo que significa que elListView
estado no se puede almacenar como miembro delFragment
.En cambio, terminé almacenando el estado en mi
Application
clase personalizada . El siguiente código debería darle una idea de cómo funciona esto:La idea básica es que almacene el estado fuera de la instancia de fragmento. Si no le gusta la idea de tener un campo estático en su clase de aplicación, supongo que podría hacerlo implementando una interfaz de fragmentos y almacenando el estado en su actividad.
Otra solución sería almacenarlo
SharedPreferences
, pero se vuelve un poco más complicado, y deberá asegurarse de borrarlo en el inicio de la aplicación a menos que desee que el estado persista en los lanzamientos de aplicaciones.Además, para evitar la "posición de desplazamiento no guardada cuando el primer elemento está visible", puede mostrar un primer elemento ficticio con
0px
altura. Esto se puede lograr anulandogetView()
en su adaptador, así:fuente
Mi respuesta es para Firebase y la posición 0 es una solución alternativa
y convertView
posición 0 a agregue un elemento en blanco que no esté utilizando
He visto este trabajo temporalmente sin molestar al usuario, espero que funcione para usted
fuente
use este código a continuación:
y cada vez que actualice sus datos use este código a continuación:
fuente
Estoy usando FirebaseListAdapter y no pude lograr que ninguna de las soluciones funcione. Terminé haciendo esto. Supongo que hay formas más elegantes, pero esta es una solución completa y funcional.
Antes de onCreate:
Dentro de FirebaseListAdapter:
en Inicio:
onStop:
Como también tuve que resolver esto para FirebaseRecyclerAdapter , estoy publicando la solución aquí para eso también:
Antes de onCreate:
Dentro de FirebaseRecyclerAdapter:
en Inicio:
onStop:
fuente
Para aclarar la excelente respuesta de Ryan Newsom y ajustarla para fragmentos y para el caso habitual de que queramos navegar de un fragmento ListView "maestro" a un fragmento "detalles" y luego volver al "maestro"
La "magia" aquí es que cuando navegamos hacia atrás desde el fragmento de detalles al fragmento ListView, la vista no se recrea, no configuramos el adaptador de ListView, ¡así que todo permanece como lo dejamos!
fuente