Quiero arreglar mis vistas de encabezado en la parte superior de la pantalla como en la imagen a continuación y sin usar bibliotecas externas.
En mi caso, no quiero hacerlo alfabéticamente. Tengo dos tipos diferentes de vistas (encabezado y normal). Solo quiero arreglar en la parte superior, el último encabezado.
android
header
android-recyclerview
sticky
Jaume Colom
fuente
fuente
Respuestas:
Aquí explicaré cómo hacerlo sin una biblioteca externa. Será una publicación muy larga, así que prepárate.
En primer lugar, permítanme reconocer a @ tim.paetz cuya publicación me inspiró a emprender un viaje de implementación de mis propios encabezados adhesivos usando
ItemDecoration
s. Tomé prestadas algunas partes de su código en mi implementación.Como ya habrás experimentado, si intentas hacerlo tú mismo, es muy difícil encontrar una buena explicación de CÓMO hacerlo realmente con la
ItemDecoration
técnica. Quiero decir, ¿cuáles son los pasos? ¿Cuál es la lógica detrás de esto? ¿Cómo hago que el encabezado se pegue en la parte superior de la lista? No saber las respuestas a estas preguntas es lo que hace que otros usen bibliotecas externas, mientras que hacerlo usted mismo con el uso deItemDecoration
es bastante fácil.Condiciones iniciales
list
de elementos de diferente tipo (no en un sentido de "tipos de Java", sino en un sentido de tipos de "encabezado / elemento").list
debe ser un elemento de encabezado.Aquí proporciono el código completo para mi
RecyclerView.ItemDecoration
llamadoHeaderItemDecoration
. Luego explico los pasos tomados en detalle.Lógica de negocios
Entonces, ¿cómo lo hago pegar?
Usted no No puede hacer un
RecyclerView
artículo de su elección, simplemente deténgase y quédese encima, a menos que sea un gurú de los diseños personalizados y sepa de memoria más de 12,000 líneas de códigoRecyclerView
. Entonces, como siempre ocurre con el diseño de la interfaz de usuario, si no puedes hacer algo, fingelo. Usted acaba de dibujar el encabezado en la parte superior de todo el usoCanvas
. También debe saber qué elementos puede ver el usuario en este momento. Simplemente sucede que esoItemDecoration
puede proporcionarle tantoCanvas
información como información sobre elementos visibles. Con esto, aquí hay pasos básicos:En el
onDrawOver
método deRecyclerView.ItemDecoration
obtener el primer elemento (superior) que es visible para el usuario.Determine qué encabezado lo representa.
Dibuje el encabezado apropiado en la parte superior de RecyclerView mediante el
drawHeader()
método.También quiero implementar el comportamiento cuando el nuevo encabezado próximo se encuentre con el superior: debería parecer que el próximo encabezado empuja suavemente el encabezado actual superior fuera de la vista y finalmente toma su lugar.
Aquí se aplica la misma técnica de "dibujar sobre todo".
Determine cuándo el encabezado superior "atascado" se encuentra con el nuevo próximo.
Obtenga este punto de contacto (es decir, la parte inferior del encabezado adhesivo que dibujó y la parte superior del próximo encabezado).
Si el elemento de la lista está traspasando este "punto de contacto", vuelva a dibujar su encabezado adhesivo para que su parte inferior esté en la parte superior del elemento de traspaso. Lo logras con el
translate()
método deCanvas
. Como resultado, el punto de partida del encabezado superior estará fuera del área visible, y parecerá que el próximo encabezado lo está "expulsando". Cuando haya desaparecido por completo, dibuja el nuevo encabezado en la parte superior.El resto se explica por comentarios y anotaciones detalladas en el código que proporcioné.
El uso es sencillo:
Su
mAdapter
deben implementarStickyHeaderInterface
para que funcione. La implementación depende de los datos que tenga.Finalmente, aquí proporciono un gif con encabezados semitransparentes, para que pueda comprender la idea y realmente ver lo que sucede debajo del capó.
Aquí está la ilustración del concepto "simplemente dibuja encima de todo". Puede ver que hay dos elementos "encabezado 1": uno que dibujamos y permanece en la parte superior en una posición atascada, y el otro que proviene del conjunto de datos y se mueve con todos los elementos restantes. El usuario no verá su funcionamiento interno, ya que no tendrá encabezados semitransparentes.
Y aquí lo que sucede en la fase de "expulsión":
Espero que haya ayudado.
Editar
Aquí está mi implementación real del
getHeaderPositionForItem()
método en el adaptador RecyclerView:Implementación ligeramente diferente en Kotlin
fuente
private View getHeaderViewForItem(int itemPosition, RecyclerView parent) { int headerPosition = mListener.getHeaderPositionForItem(itemPosition); if(headerPosition != mCurrentHeaderIndex) { mCurrentHeader = mListener.createHeaderView(headerPosition, parent); mCurrentHeaderIndex = headerPosition; } return mCurrentHeader; }
La forma más fácil es crear una Decoración de artículos para su RecyclerView.
}
XML para su encabezado en recycler_section_header.xml:
Y finalmente para agregar la Decoración del artículo a su RecyclerView:
Con esta Decoración del artículo, puede hacer que el encabezado quede fijo / adhesivo o no con solo un booleano al crear la Decoración del artículo.
Puede encontrar un ejemplo de trabajo completo en github: https://github.com/paetztm/recycler_view_headers
fuente
wrap_content
), también querrá ejecutarfixLayoutSize
después de configurar el texto del título.He hecho mi propia variación de la solución de Sevastyan anterior
... y aquí está la implementación de StickyHeaderInterface (lo hice directamente en el adaptador de reciclador):
Entonces, en este caso, el encabezado no es solo dibujar en el lienzo, sino ver con selector o ondulación, clicklistener, etc.
fuente
recyclerView.addItemDecoration(HeaderItemDecoration(recyclerView, adapter))
. Lo siento, no puedo encontrar un ejemplo de implementación, que utilicé. He editado la respuesta - agregué un texto a los comentariosa cualquiera que busque una solución al problema de parpadeo / parpadeo cuando ya lo haya hecho
DividerItemDecoration
. Parece que lo he resuelto así:Esto parece estar funcionando, pero ¿alguien puede confirmar que no rompí nada más?
fuente
Puede verificar y tomar la implementación de la clase
StickyHeaderHelper
en mi proyecto FlexibleAdapter y adaptarla a su caso de uso.Pero, sugiero usar la biblioteca, ya que simplifica y reorganiza la forma en que normalmente implementa los adaptadores para RecyclerView: no reinvente la rueda.
También diría que no use decoradores o bibliotecas obsoletas, así como no use bibliotecas que solo hagan 1 o 3 cosas, tendrá que fusionar las implementaciones de otras bibliotecas usted mismo.
fuente
Decorator
s?Otra solución, basada en el oyente scroll. Las condiciones iniciales son las mismas que en la respuesta de Sevastyan
Diseño para ViewHolder y encabezado adhesivo.
item_header.xml
Diseño para RecyclerView
Clase para HeaderItem.
Es todo uso. La implementación del adaptador, ViewHolder y otras cosas, no es interesante para nosotros.
Interfaz para la vista de encabezado de enlace.
fuente
for (int i = position; position >= 0; i--){ //should be i >= 0
Yo,
Así es como lo hace si desea un solo tipo de soporte cuando comienza a salir de la pantalla (no nos interesan las secciones). Solo hay una manera sin romper la lógica interna de RecyclerView de reciclar elementos y es inflar una vista adicional en la parte superior del elemento de encabezado de recyclerView y pasar datos al mismo. Dejaré hablar el código.
Y luego solo haces esto en tu adaptador:
Donde YOUR_STICKY_VIEW_HOLDER_TYPE es viewType de lo que se supone que es un soporte adhesivo.
fuente
Para aquellos que puedan preocuparse. Según la respuesta de Sevastyan, si desea que sea horizontal, desplácese. Simplemente cambiar todo
getBottom()
agetRight()
ygetTop()
agetLeft()
fuente
La respuesta ya ha estado aquí. Si no desea utilizar ninguna biblioteca, puede seguir estos pasos:
Explicación:
En el
onCreateViewHolder
método podemos verificarviewType
y, dependiendo del valor (nuestro tipo "especial"), inflamos un diseño especial.Por ejemplo:
donde
class ItemElement
yclass TitleElement
puede parecer ordinarioViewHolder
:Entonces la idea de todo eso es interesante. Pero estoy interesado si es efectivo, porque necesitamos ordenar la lista de datos. Y creo que esto reducirá la velocidad. Si tienes alguna idea al respecto, escríbeme :)
Y también la pregunta abierta: es cómo mantener el diseño "especial" en la parte superior, mientras los artículos se reciclan. Tal vez combine todo eso con
CoordinatorLayout
.fuente