¿Cómo se actualizan los datos que se muestran en RecyclerView
(llamando notifyDataSetChanged
a su adaptador) y se asegura de que la posición de desplazamiento se restablezca exactamente donde estaba?
En el caso de que ListView
todo sea bueno, todo lo que se necesita es recuperar getChildAt(0)
, verificar getTop()
y llamar setSelectionFromTop
con los mismos datos exactos después.
No parece posible en el caso de RecyclerView
.
Supongo que se supone que debo usar lo LayoutManager
que de hecho proporciona scrollToPositionWithOffset(int position, int offset)
, pero ¿cuál es la forma correcta de recuperar la posición y el desplazamiento?
layoutManager.findFirstVisibleItemPosition()
y layoutManager.getChildAt(0).getTop()
?
¿O hay una forma más elegante de hacer el trabajo?
fuente
Respuestas:
Yo uso este. ^ _ ^
Es más simple, ¡espero que te ayude!
fuente
Tengo un problema bastante similar. Y se me ocurrió la siguiente solución.
Usar
notifyDataSetChanged
es una mala idea. Debería ser más específico, luegoRecyclerView
guardará el estado de desplazamiento para usted.Por ejemplo, si solo necesita actualizar, o en otras palabras, desea que cada vista se vuelva a enlazar, simplemente haga esto:
fuente
notifyDataSetChanged
la posición de desplazamiento cambiaría mostrando los nuevos elementos. Sin embargo, si utilizarnotifyItemRangeInserted(0, newItems.size() - 1)
laRecyclerView
mantiene el estado de desplazamiento.EDITAR: Para restaurar exactamente la misma posición aparente , como en, hacer que se vea exactamente como lo hizo, necesitamos hacer algo un poco diferente (vea a continuación cómo restaurar el valor de scrollY exacto):
Guarde la posición y el desplazamiento de esta manera:
Y luego restaure el pergamino así:
Esto restaura la lista a su posición aparente exacta . Aparente porque se verá igual para el usuario, pero no tendrá el mismo valor de scrollY (debido a posibles diferencias en las dimensiones del diseño horizontal / vertical).
Tenga en cuenta que esto solo funciona con LinearLayoutManager.
--- Debajo de cómo restaurar el scrollY exacto, lo que probablemente hará que la lista se vea diferente ---
Aplicar un OnScrollListener así:
Esto almacenará la posición de desplazamiento exacta en todo momento en mScrollY.
Almacene esta variable en su Bundle y restáurela en restauración de estado a una variable diferente , la llamaremos mStateScrollY.
Después de la restauración del estado y después de que su RecyclerView haya restablecido todos sus datos, restablezca el desplazamiento con esto:
Eso es.
Tenga cuidado, que restaure el desplazamiento a una variable diferente, esto es importante, porque el OnScrollListener será llamado con .scrollBy () y posteriormente establecerá mScrollY al valor almacenado en mStateScrollY. Si no hace esto, mScrollY tendrá el doble del valor de desplazamiento (porque OnScrollListener funciona con deltas, no con desplazamientos absolutos).
El ahorro estatal en actividades se puede lograr así:
Y para restaurar, llame a esto en su onCreate ():
El guardado de estado en fragmentos funciona de manera similar, pero el guardado de estado real necesita un poco de trabajo adicional, pero hay muchos artículos que tratan sobre eso, por lo que no debería tener problemas para descubrir cómo, los principios para guardar el scrollY y restaurarlo sigue siendo el mismo.
fuente
Sí, puede resolver este problema haciendo que el constructor del adaptador solo una vez, estoy explicando la parte de codificación aquí:
Ahora puede ver que he comprobado que el adaptador es nulo o no y solo inicializo cuando es nulo.
Si el adaptador no es nulo, entonces estoy seguro de que he inicializado mi adaptador al menos una vez.
Así que simplemente agregaré una lista al adaptador y llamaré a notifydatasetchanged.
RecyclerView siempre mantiene la última posición desplazada, por lo tanto, no tiene que almacenar la última posición, simplemente llame a notifydatasetchanged, la vista de reciclador siempre actualiza los datos sin ir al principio.
Gracias Happy Coding
fuente
Mantenga la posición de desplazamiento usando la respuesta @DawnYu para ajustar
notifyDataSetChanged()
así:fuente
La respuesta principal de @DawnYu funciona, pero la vista de reciclaje primero se desplazará hacia la parte superior y luego volverá a la posición de desplazamiento deseada, lo que provocará una reacción de "parpadeo" que no es agradable.
Para actualizar la vista de reciclaje, especialmente después de venir de otra actividad, sin parpadear y manteniendo la posición de desplazamiento, debe hacer lo siguiente.
Espero que esto ayude.
fuente
No he usado Recyclerview pero lo hice en ListView. Código de muestra en Recyclerview:
Es el oyente cuando el usuario se desplaza. La sobrecarga de rendimiento no es significativa. Y la primera posición visible es precisa de esta manera.
fuente
findFirstVisibleItemPosition
devuelve "la posición del adaptador de la primera vista visible", pero ¿qué pasa con el desplazamiento?La solución aquí es seguir desplazándose por la vista de reciclaje cuando llega un mensaje nuevo.
El método onChanged () detecta la acción realizada en la vista de reciclaje.
fuente
Eso me está funcionando en Kotlin.
El desplazamiento de desplazamiento no cambia.
fuente
Tuve este problema con una lista de elementos que tenían un tiempo en minutos hasta que estaban "vencidos" y necesitaban actualizarse. Actualizaría los datos y luego llamaría
y se desplazaría hasta la parte superior cada vez. Lo reemplacé con
y estuvo bien. Ninguno de los otros métodos en este hilo funcionó para mí. Sin embargo, al usar este método, hizo que cada elemento individual parpadeara cuando se actualizó, por lo que también tuve que poner esto en el fragmento principal onCreateView
fuente
Si tiene uno o más EditTexts dentro de los elementos de una vista de reciclaje, desactive el enfoque automático de estos, colocando esta configuración en el elemento primario vista vista de reciclaje:
Tuve este problema cuando comencé otra actividad lanzada desde un elemento de la vista de reciclaje, cuando regresé y configuré una actualización de un campo en un elemento con notificarItemChanged (posición) el desplazamiento de RV se mueve, y mi conclusión fue que, el enfoque automático de EditText Artículos, el código anterior resolvió mi problema.
mejor.
fuente
Regrese si la posición anterior y la posición es la misma;
fuente