>

¿SpanSizeLookup? - La magia de los RecyclerViews #Android

Francisco Manuel López Jurado     Colaboraciones    12/05/2017


Diseñadores contra desarrolladores, una guerra abierta desde que el diseño tomó suma importancia en el ecosistema de las aplicaciones móviles. Ya no se trata de tener sólo la app más funcional sino que, además, debe ser agradable a la vista, fluída y con animaciones casi imposibles. Debido a esto surgió un nuevo diseño rompedor en los listados, traído del diseño traído de la web llegaron las listas con elementos con distintos anchos y diseños.

Las listas tipadas ya existían anteriormente a los RecyclerViews ya que era propio de los Adapters. Podíamos crear listas o grids usando componentes como ListViews o GridViews, sin embargo, el gran problema llegaba cuando queríamos que los elementos de esa lista fueran dinámicos tanto en ancho como en alto. Por ello surgió el componente RecyclerView.LayoutManayer. En este tutorial crearemos una lista con dos tipos de vistas (Categoría y Componente), para ello usaremos la misma lógica que se seguían en los antiguos adapters pero adaptado al nuevo (RecyclerView.Adapter). Además de esto, haremos que los elementos de distinto tipo se presenten de distinta manera, consiguiendo que nuestra lista tenga una estructura dinámica de elementos.

¿Qué es RecyclerView.LayoutManager?

Es el encargado de medir y colocar las vistas dentro de nuestros RecyclerViews, además de ser el encargado del reciclaje de nuestras vistas (se acabó la implementación del patrón ViewHolder por nuestra cuenta). Podemos crear tanto listas normales, grids, listas escalonadas, etc, en resumen, multitud de configuraciones a nuestro gusto.

De él nace este post, ya que usaremos una extensión de este componente llamado GridLayoutManager junto con un método que normalmente pasa desapercibido pero que se torna en casi indispensable cuando quieres hacer listas dinámicas.

SpanSizeLookup, comienza lo bueno

Se trata de una clase auxiliar que establece el número de “espacios” que ocupa cada elemento dentro de un Recycler. Por defecto, el espacio que ocupará cada elemento es 1.

Establecemos nuestro propio SpanSizeLookup

gridlayoutmanager

Como podemos ver en la siguiente porción de código, en función del tipo de nuestra vista estableceremos un span u otro. Para nuestro ejemplo hemos establecido:

  • Un GridLayoutManager de dos columnas.
  • Si la vista es de tipo categoría, debe ocupar las dos columnas posibles.
  • Si la vista es de tipo componente, deberá ocupar una columna de las dos posibles.

GetItemViewType

Para entender completamente cómo funciona este ejemplo, es necesario comentar dicho método. En él debemos definir nuestra lógica encargada de diferenciar nuestros objetos y con ello, las vistas para cada uno de ellos. Hemos extraído el siguiente método del adapter del que debemos saber:

  • Hemos creado un modelo base llamado BaseModel y dos clases que extienden de él, CategoryModel y ComponentModel.
  • Establecemos el id de las distintas tipos de vistas que tenemos.
  • Para devolver los distintos tipos usaremos en este caso “instanceof” y retornaremos el id de la vista en función.

Finalmente el método quedaría así:

getItemViewType

Gracias a la conjunción de estos métodos conseguiremos que nuestra vista se vea de la siguiente forma:

resultado final

Bonus

Para continuar con el anterior post en el que dimos una introducción a ConstraintLayout, en este ejemplo hemos creado nuestros layout con dicho componente.

CategoryRow

En el caso de las categorías tenemos:

  • Una imagen de fondo con un tamaño de alto de 200dp que las constraints necesarias para que ocupe todo el alto y ancho de la vista.
  • Un ConstraintLayout alineado abajo pero por encima de la imagen, dentro de él nos encontramos con un elemento TextView centrado.

Adjuntamos una imagen de cómo ha quedado:

CategoryRow Constraint Layout

ComponentRow

Esta vista es algo más compleja y ponemos a prueba al ConstraintLayout:

  • Una imagen alineada arriba
  • Un ConstraintLayout alineado en la parte inferior de la imagen comentada. Dentro de él encontramos un ImageView alineado a la izquierda y centrado, éste se ocultará en función de una variable del modelo. A su derecha encontramos un elemento TextView centrado verticalmente.

Adjuntamos una imagen cómo ha quedado:

CompontentRow ConstraintLayout

En resumen, RecyclerView proporciona herramientas que harán que cada vez sea más fácil la customización de las listas y el renderizado de las mismas consiguiendo así que nuestras apps estén siempre a la altura de lo que demanda el mercado.


Sobre el autor

Francisco Manuel López Jurado   

Apasionado de la tecnología y todo lo que la rodea. Desarrollador Senior Android e iOS.