Inicio Android Controles de selección: RecyclerView

Controles de selección: RecyclerView

por admin

Actualizado: Mayo 2020

En este nuevo artículo del curso hablaremos del control RecyclerView, que nos ayudará a crear controles de tipo lista y tabla. Este control llegó con Android 5.0 como una mejor alternativa a los antiguos controles ListView (lista) y GridView (tabla) de versiones anteriores, aportando en la mayoría de ocasiones flexibilidad de sobra para suplir la funcionalidad de ambos, e ir incluso más allá.

RecyclerView nos va a permitir mostrar en pantalla colecciones de datos. Pero lo va a hacer de una forma algo distinta a la que estábamos habituados con los controles anteriores. Y es que RecyclerView no va a hacer «casi nada» por sí mismo, sino que se va a sustentar sobre otros componentes complementarios para determinar cómo acceder a los datos y cómo mostrarlos. Los más importantes serán los siguientes:

  • RecyclerView.Adapter
  • RecyclerView.ViewHolder
  • LayoutManager
  • ItemDecoration
  • ItemAnimator

El primer componente deberíais ya reconocerlo si habéis revisado el capítulo anterior del curso dedicado al control Spinner. De igual forma que vimos para el componente anterior, un RecyclerView se apoyará también en un adaptador para trabajar con nuestros datos, en este caso un adaptador que herede de la clase RecyclerView.Adapter. La peculiaridad en esta ocasión es que este tipo de adaptador utilizará internamente el patrón view holder que dotará de una mayor eficiencia al control, y de ahí la necesidad del segundo componente de la lista anterior, RecyclerView.ViewHolder.

Por resumirlo de alguna forma, un view holder se encargará de contener y gestionar las vistas o controles asociados a cada elemento individual de la lista. El control RecyclerView se encargará de crear tantos view holder como sea necesario para mostrar los elementos de la lista que se ven en pantalla y los gestionará eficientemente de forma que no tenga que crear nuevos objetos para mostrar más elementos de la lista al hacer scroll, sino que tratará de «reciclar» aquellos que ya no sirven por estar asociados a otros elementos de la lista que ya han salido de la pantalla.

NOTA: En esta nueva versión actualizada del curso no trataré los controles ListView y GridView, ya que actualmente la opción recomendada para sustituir la funcionalidad de ambos es RecyclerView, pero si quieres entender mejor qué significa esto del patrón view holder te recomiendo que eches un vistazo a los dos artículos sobre ListView de la versión anterior del curso (listas y listas optimizadas). El código de dichos artículos está escrito en java, pero aún así te ayudarán a aclarar algunos conceptos y entender o justificar la necesidad del view holder.

Los tres siguientes componentes de la lista sí son una novedad, siendo el más importante el primero de ellos, el LayoutManager. Anteriormente, cuando decidíamos utilizar un ListView ya sabíamos que nuestros datos se representarían de forma lineal con la posibilidad de hacer scroll en un sentido u otro, y en el caso de elegir un GridView la representación sería tabular. Una vista de tipo RecyclerView por el contrario no determina por sí sola la forma en que se van a mostrar en pantalla los elementos de nuestra colección, sino que va a delegar esa tarea a otro componente llamado LayoutManager, que también tendremos que crear y asociar al RecyclerView para su correcto funcionamiento. Por suerte, el SDK incorpora de serie algunos LayoutManager para las representaciones más habituales de los datos: lista vertical u horizontal (LinearLayoutManager), tabla tradicional (GridLayoutManager) y tabla apilada o de celdas no alineadas (StaggeredGridLayoutManager). Por tanto, siempre que optemos por alguna de estas distribuciones de elementos no tendremos que crear nuestro propio LayoutManager personalizado, aunque por supuesto nada nos impide hacerlo, y ahí uno de los puntos fuertes de este componente: su flexibilidad.

Los dos últimos componentes de la lista se encargarán de definir cómo se representarán algunos aspectos visuales concretos de nuestra colección de datos (más allá de la distribución definida por el LayoutManager), por ejemplo marcadores o separadores de elementos, y de cómo se animarán los elementos al realizarse determinadas acciones sobre la colección, por ejemplo al añadir o eliminar elementos.

Como hemos comentado, no siempre será obligatorio implementar todos estos componentes para hacer uso de un RecyclerView. Lo más habitual será implementar el Adapter y el ViewHolder, utilizar alguno de los LayoutManager predefinidos, y sólo en caso de necesidad crear los ItemDecoration e ItemAnimator necesarios para dar un toque de personalización especial a nuestra aplicación.

Para describir el uso del control RecyclerView de la forma más completa posible, aunque sin complicarnos de forma innecesaria, vamos a crear una aplicación de ejemplo que mostrará una lista/tabla de elementos formados cada uno de ellos por dos lineas de texto que llamaremos título y subtítulo (por supuesto se podrían añadir muchos más elementos, por ejemplo imágenes, checkboxes, … en definitiva cualquier control disponible).

Vamos a empezar por la parte más sencilla, crearemos un nuevo proyecto en Android Studio y añadiremos a la sección de dependencias del fichero build.gradle del módulo principal la referencia a la librería de soporte androidx.recyclerview, lo que nos permitirá el uso del componente RecyclerView en la aplicación:

dependencies {
    ...
    implementation "androidx.recyclerview:recyclerview:1.1.0"
}

Tras esto ya podremos añadir un nuevo RecyclerView al layout de nuestra actividad principal:

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

El siguiente paso también es sencillo, crearemos una clase que encapsulará los dos datos que compondrán cada elemento a mostrar en la tabla. La llamaremos Titular y se puede definir mediante una clase de datos de kotlin:

data class Titular(val titulo: String, val subtitulo: String)

En cada elemento de la lista queremos mostrar ambos datos, por lo que el siguiente paso será crear un layout XML con la estructura visual que deseemos. En mi caso voy a mostrarlos en dos etiquetas de texto (TextView), la primera de ellas en negrita y con un tamaño de letra un poco mayor. Llamaremos a este layout «listitem_titular.xml» y lo colocaremos en la carpeta /app/res/layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="?android:attr/selectableItemBackground" >

    <TextView android:id="@+id/lblTitulo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:textSize="24sp" />

    <TextView android:id="@+id/lblSubtitulo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="normal"
        android:textSize="16sp" />
</LinearLayout>

A continuación escribiremos nuestro adaptador. Este adaptador deberá extender a la clase RecyclerView.Adapter, de la cual tendremos que sobrescribir principalmente tres métodos:

  • onCreateViewHolder(). Encargado de crear los nuevos objetos ViewHolder necesarios para los elementos de la colección.
  • onBindViewHolder(). Encargado de actualizar los datos de un ViewHolder ya existente.
  • onItemCount(). Indica el número de elementos de la colección de datos.

Para nuestra aplicación de ejemplo utilizaré como fuente de datos un simple array de objetos de tipo Titular.

Como ya hemos comentado, la clase RecyclerView.Adapter nos obligará de cierta forma a hacer uso del patrón view holder. Por tanto, para poder seguir con la implementación del adaptador lo primero que definiremos será el ViewHolder necesario para nuestro caso de ejemplo. Lo definiremos como clase interna a nuestro adaptador, extendiendo de la clase RecyclerView.ViewHolder, y será bastante sencillo, tan sólo tendremos que incluir como atributos las referencias a los controles del layout de un elemento de la lista (en nuestro caso los dos TextView) e inicializarlas en el constructor utilizando como siempre el método findViewById() sobre la vista recibida como parámetro. Por comodidad añadiremos también un método auxiliar, que llamaremos bindTitular(), que se encargue de asignar los contenidos de los dos cuadros de texto a partir de un objeto Titular cuando nos haga falta.

class AdaptadorTitulares(private val datos: Array<Titular>) :
    RecyclerView.Adapter<AdaptadorTitulares.TitularesViewHolder>() {

    class TitularesViewHolder(val item: View) : RecyclerView.ViewHolder(item) {
        val lblTitulo = item.findViewById(R.id.lblTitulo) as TextView
        val lblSubtitulo = item.findViewById(R.id.lblSubtitulo) as TextView

        fun bindTitular(titular: Titular){
            lblTitulo.text = titular.titulo
            lblSubtitulo.text = titular.subtitulo
        }
    }
}

Finalizado nuestro ViewHolder podemos ya seguir con la implementación del adaptador sobrescribiendo los métodos indicados. En el método onCreateViewHolder() nos limitaremos a inflar (construir) una vista a partir del layout correspondiente a los elementos de la lista (listitem_titular), y crear y devolver un nuevo ViewHolder llamando al constructor de nuestra clase TitularesViewHolder pasándole dicha vista como parámetro.

Los dos métodos restantes son aún más sencillos. En onBindViewHolder() tan sólo tendremos que recuperar el objeto Titular correspondiente a la posición recibida como parámetro y asignar sus datos sobre el ViewHolder también recibido como parámetro. Por su parte, getItemCount() tan sólo devolverá el tamaño del array de datos.

class AdaptadorTitulares(private val datos: Array<Titular>) :
    RecyclerView.Adapter<AdaptadorTitulares.TitularesViewHolder>() {

    //...

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TitularesViewHolder {
        val item = LayoutInflater.from(parent.context)
            .inflate(R.layout.listitem_titular, parent, false) as LinearLayout

        return TitularesViewHolder(item)
    }

    override fun onBindViewHolder(holder: TitularesViewHolder, position: Int) {
        val titular = datos[position]
        holder.bindTitular(titular)
    }

    override fun getItemCount() = datos.size
}

Con esto tendríamos finalizado el adaptador, por lo que ya podríamos asignarlo al RecyclerView en nuestra actividad principal. Tan sólo tendremos que crear nuestro adaptador personalizado AdaptadorTitulares pasándole como parámetro la lista de datos y asignarlo al control RecyclerView mediante su propiedad adapter.

class MainActivity : AppCompatActivity() {

    private lateinit var recView : RecyclerView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        recView = findViewById(R.id.recView)

        val datos =
            Array(50) { i -> Titular("Titulo $i", "Subtítulo Item $i") }

        val adaptador = AdaptadorTitulares(datos) 

        recView.setHasFixedSize(true)

        recView.layoutManager =
            LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

        recView.adapter = adaptador
    }
}

Algunos comentarios más sobre el código anterior. He aprovechado el método onCreate() para inicializar el array de datos de ejemplo (atributo datos) con 50 titulares con un texto tipo. Tras obtener la referencia al RecyclerView he incluido también una llamada a setHasFixedSize(). Aunque esto no es obligatorio, sí es conveniente hacerlo cuando tengamos certeza de que el tamaño de nuestro RecyclerView no va a variar (por ejemplo debido a cambios en el contenido del adaptador), ya que esto permitirá aplicar determinadas optimizaciones sobre el control.

Adicionalmente, como último paso antes de asociar el adaptador al RecyclerView, le hemos creado y asignado un LayoutManager para determinar la forma en la que se distribuirán los datos en pantalla. Como ya dijimos, si nuestra intención es mostrar los datos en forma de lista o tabla (al estilo de los antiguos ListView o GridView) no tendremos que implementar nuestro propio LayoutManager (una tarea nada sencilla), ya que el SDK proporciona varias clases predefinidas para los tipos más habituales. En nuestro caso particular queremos mostrar los datos en forma de lista con desplazamiento vertical. Para ello tenemos disponible la clase LinearLayoutManager, por lo que tan sólo tendremos que instanciar un objeto de dicha clase indicando en el constructor la orientación del desplazamiento (LinearLayoutManager.VERTICAL o LinearLayoutManager.HORIZONTAL) y lo asignamos al RecyclerView mediante su propiedad layoutManager.

Llegados aquí ya sería posible ejecutar la aplicación de ejemplo para ver cómo quedan nuestros datos en pantalla, ya que los dos componentes que nos falta por comentar (ItemDecoration e ItemAnimator) no son obligatorios para el funcionamiento básico del control RecyclerView.

Lo bueno de todo lo que llevamos hasta el momento, es que si cambiáramos de idea y quisiéramos mostrar los datos de forma tabular tan sólo tendríamos que cambiar la asignación del LayoutManager anterior y utilizar un GridLayoutManager, al que pasaremos como parámetro el número de columnas a mostrar.

recView.layoutManager = GridLayoutManager(this, 3)

Con este simple cambio la aplicación quedaría con el siguiente aspecto:

El siguiente paso que nos podemos plantear es cómo responder a los eventos que se produzcan sobre el RecyclerView, como opción más habitual el evento click sobre un elemento de la lista. Para sorpresa de muchos la clase RecyclerView no incluye un evento onItemClick como ocurría en el caso de ListView.  Una vez más, RecyclerView delega también esta tarea a otro componente, en este caso a la propia vista que conforma cada elemento de la colección.

Será por tanto dicha vista a la que tendremos que asociar el código a ejecutar como respuesta al evento click. Esto podemos hacerlo de diferentes formas, yo tan sólo mostraré una de ellas. En nuestro caso aprovecharemos el método onBindViewHolder() para asignar a su vista asociada el evento onClick. Para poder asignar el evento desde fuera del adaptador, incluiremos la función a llamar como nuevo atributo del adaptador. Adicionalmente, por comodidad, pasaremos como parámetro de esta función el dato (en nuestro ejemplo el objeto Titular) contenido en ese elemento.

Creo que es más fácil verlo sobre el código:

class AdaptadorTitulares(
    private val datos: Array<Titular>, 
    private val clickListener : (Titular) -> Unit) :
        RecyclerView.Adapter<AdaptadorTitulares.TitularesViewHolder>() {

    //...

    override fun onBindViewHolder(holder: TitularesViewHolder, position: Int) {
        val titular = datos[position]
        holder.bindTitular(titular)

        holder.item.setOnClickListener{clickListener(titular)};
    }

    //...
}

Por su parte, para añadir la implementación del evento desde la actividad principal, modificaríamos la creación del adaptador de la siguiente forma:

//...
val datos =
    Array(50) { i -> Titular("Titulo $i", "Subtítulo Item $i") }

val adaptador = AdaptadorTitulares(datos) {
    Log.i("DemoRecView", "Pulsado el elemento: ${it.titulo}")
}
//...

En este caso al pulsar sobre un elemento de la lista tan sólo escribiremos, por ejemplo, un mensaje de log indicando la posición en la lista del elemento pulsado. Podéis ver los mensajes de log de la aplicación en las vistas inferiores llamadas Run y Logcat de Android Studio.

Con esto ya podríamos volver a ejecutar la aplicación de ejemplo y comprobar si todo funciona correctamente según lo definido al pulsar sobre los elementos de la lista.

Por último vamos a describir brevemente los dos componentes restantes relacionados con RecyclerView.

En primer lugar nos ocuparemos de ItemDecoration. Los ItemDecoration nos servirán para personalizar el aspecto de un RecyclerView más allá de la distribución de los elementos en pantalla. El ejemplo típico de esto son los separadores o divisores de una lista. 

Crear un ItemDecoration personalizado no es una tarea demasiado fácil, o al menos no inmediata, por lo que por ahora no nos detendremos mucho en ello. Pero para el caso de los separadores de lista Android ya nos proporciona de serie la clase DividerItemDecoration. Para utilizar este componente deberemos simplemente crear el objeto y asociarlo a nuestro RecyclerView mediante addItemDecoration() en nuestra actividad principal:

//...
recView.layoutManager =
    LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

recView.addItemDecoration(
    DividerItemDecoration(this, DividerItemDecoration.VERTICAL))

recView.adapter = adaptador
//...

Como nota adicional indicar que podremos añadir a un RecyclerView tantos ItemDecoration como queramos, que se aplicarán en el mismo orden que se hayan añadido con addItemDecoration().

Por último hablemos muy brevemente de ItemAnimator. Un componente ItemAnimator nos permitirá definir las animaciones que mostrará nuestro RecyclerView al realizar las acciones más comunes sobre un elemento (añadir, eliminar, mover, modificar). Este componente tampoco es sencillo de implementar, pero por suerte el SDK también proporciona una implementación por defecto que puede servirnos en la mayoría de ocasiones, aunque por supuesto podremos personalizar creando nuestro propio ItemAnimator. Esta implementación por defecto se llama DefaultItemAnimator y podemos asignarla al RecyclerView mediante su propiedad itemAnimator.

//...
recView.layoutManager =
    LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

recView.addItemDecoration(
    DividerItemDecoration(this, DividerItemDecoration.VERTICAL))

recView.itemAnimator = DefaultItemAnimator()

recView.adapter = adaptador
//...

Para probar su funcionamiento vamos a añadir a nuestro layout principal tres botones con las opciones de añadir, eliminar y mover un elemento de la lista (concretamente el segundo elemento de la lista). La implementación de estos botones es bastante sencilla y la incluiremos también en el onCreate() de la actividad principal:

btnInsertar = findViewById(R.id.btnInsertar)
btnEliminar = findViewById(R.id.btnEliminar)
btnMover = findViewById(R.id.btnMover)

//...

btnInsertar.setOnClickListener {
    datos.add(1, Titular("Nuevo Titular", "Subtitulo Nuevo Titular"))
    adaptador.notifyItemInserted(1)
}

btnEliminar.setOnClickListener {
    datos.removeAt(1)
    adaptador.notifyItemRemoved(1)
}

btnMover.setOnClickListener {
    val titularAux = datos[1]
    datos[1] = datos[2].also { datos[2] = datos[1] }
    adaptador.notifyItemMoved(1, 2)
}

Lo más interesante a destacar del código anterior son los métodos de notificación de cambios del adaptador. Tras realizar cada acción sobre los datos debemos llamar a su método de notificación correspondiente de forma que pueda refrescarse correctamente el control y se ejecute la animación correspondiente. Así, tras añadir un elemento llamaremos a notifyItemInserted() con la posición del nuevo elemento, al eliminar un datos llamaremos a notifyItemRemoved(), al actualizar un dato a notifyItemChanged() y al moverlo de lugar a notifyItemMoved().

Ejecutemos por última vez la aplicación de ejemplo para revisar que las animaciones por defecto funcionan también según lo esperado.

CÓDIGO DEL ARTÍCULO: Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este artículo accediendo a la pagina del curso en GitHub.

También te puede interesar

34 comentarios

Guillermo 08/03/2015 - 14:58

¡Muy buen tutorial, como siempre! Los cambios respecto al ListView eran muchos, y creo que en esta entrada la mayoría de lectores aclararán sin problema sus dudas. Sigue así!

Responder
felix 16/09/2020 - 11:26

buen tutorial, tengo algunas dificultades con recycler en mi proyecto necesito pintar dos items distintos de un mismo objeto osea 2 valores del mismo objeto que tienen el mismo id

relationsArray.add(Relationship(1, «Nieto», «Nieta», «Abuelo», «Abuela»))

relationsArray.add(Relationship(2, «Hijo», «Hija», «Padre», «Madre»))

relationsArray.add(Relationship(3, «Cuidador», «Cuidadora», «Abuelo», «Abuela»))

de este array de objetos necesito sacar un item para la posicion 1 y otro para la posicion 2 del array para poder pasar el id

Responder
Juan Pablo 23/03/2015 - 21:11

Recién descubro esta serie de tuturiales. Debo decir que siempre busqué manuales o tutoriales en inglés, porque por lo general contienen más información y se encuentran actualizados. Pero la verdad es que este blog es de lo mejor que encontré en la Web, incluyendo páginas y libros tanto en español como en inglés.
Felicitaciones! Y muchas gracias por hacer disponible esta información.
Saludos desde Argentina

Responder
adrian 10/05/2015 - 18:59

Excelente tutoriales! Explicando paso a paso y publicando el ejercicio en git hub.
Una consulta, es posible poner en onclick listener los dos txtview por separado para realizar diferentes acciones???

Responder
Óscar 11/05/2015 - 15:08

Qué bueno!!! Muy bien explicado.

Gracias :)

Responder
Jose Alberto 19/05/2015 - 9:55

Buenas!!

Genial el tutorial!! igual que el resto por otra parte. Tengo una duda. Quiero hacer un control personalizado que yo creo que encaja con un recyclerview horizontal. Me gustaria que el primer elemento empezara en la mitad de la pantalla y que se empezaran a desplazarse de izquierda a derecha. Cualquier tipo de ayuda será bien recibida.
Gracias!!

Responder
Guillermo 23/05/2015 - 18:01

gracias estoy aprendiendo a desarrollar aplicacione en androit bueno tutorial si me puedes anviar mas informacion se los agradeceria sobre todos de las funciones gracias

Responder
Emanuel 11/06/2015 - 14:54

Muy buenos tutoriales! gracias por tomarte el tiempo. :)

Responder
Fernando 19/06/2015 - 8:59

Un placer siempre leer este blog que tanto me ayudó cuando estaba empezando y tanto me sigue ayudando ahora.

¿Tienes pensado escribir un post con aspectos más avanzados del RecyclerView?

Responder
JaviSali 05/08/2015 - 16:37

Hola.
un aporte genial!!!

lo que yo estoy aprendiendo ahora y me gustaria saver como implementar a este ejemplo una imagen en cada entrada del recyclerView.

alguien me puede ayudar.

Saludos.

Responder
Álvaro 07/08/2015 - 13:04

Buenas! Genial aporte :) mil ths,

En cuanto a JaviSali, supongo que bastaría con añadir una imagen en el prototipo de la celda y luego asignarla. Yo estoy retomando ahora android así que no te lo aseguro 100% pero vamos, la lógica me dice que así sería xD

Saludos.

Responder
Luis 13/08/2015 - 0:59

Gracias por tus aportes muy interesante, tengo una duda, existe algún problema al crear el RecyclerView, dentro de un FrameLayout android.support.v4.app.Fragment?

gracias por responder.

Responder
JaviSali 14/08/2015 - 11:26

Hola.

Alvaro ya lo solucione, hay que implementar en la clase que definimos nuestros datos como un entero.
en tonces se le pasa como el identificatico de la foto (R.drawable.»nombre foto»), y en el adaptador se trata como la imagen.

al ejemplo abria que añadir lo siguiente.
Class Titular:

public class Titular {
private String titulo;
private String subtitulo;
private int imagen;

public Titular(String tit, String imp, int img){

titulo = tit;
subtitulo = imp;
imagen = img;

}

public String getTitulo(){return titulo;}

public String getSubtitulo(){
return subtitulo;
}

public int getImagen(){ return imagen;
}

}

Class Adaptador:
public static class TitularesViewHolder extends RecyclerView.ViewHolder {

private TextView txtTitulo;
private TextView txtSubtitulo;
private ImageView imagen;

public TitularesViewHolder(View itemView) {
super(itemView);

txtTitulo = (TextView)itemView.findViewById(R.id.LblTitulo);
txtSubtitulo = (TextView)itemView.findViewById(R.id.LblSubtitulo);
imagen = (ImageView) itemView.findViewById(R.id.imagen);

}

public void bindTitular(Titular t) {

txtTitulo.setText(t.getTitulo());
txtSubtitulo.setText(t.getSubtitulo());
imagen.setImageResource(t.getImagen());

}
}

y en la actividad al insertar:

datos.add(new Titular(«Título » + i, «Subtítulo item » + i, R.drawable.foto))

Gracias.

Responder
Alvaro 24/08/2015 - 20:04

Muy buen tutorial… una duda… como puedo hacer para muestre lo que contiene el item seleccionado, por ejemplo al presionar un elemento que muestre «titulo 0» en ves de la posición como se muestra en el ejemplo.

Saludos

Responder
RecyclerView: ItemDecoration | CYBERI@ 18/11/2015 - 0:51

[…] Las RecyclerView nos permiten mostrar de una manera visual y agradable grandes colecciones de datos con una gran flexibilidad que hasta ahora no se podía conseguir las ListView o las GridView. Esto es gracias a que el RecyclerView no hace casi nada por si mismo, si no que aprovecha los componentes complementarios de los que dispone para determinar tanto la forma de acceso, como la manera de visualizar los datos. Antes del salto se pueden ver los componentes más importantes y después del salto entraremos a ver con detalle el ItemDecoration. […]

Responder
oscar daniel 04/12/2015 - 1:30

me sale el siguiente error al pegar el codigo XML del recyclerview

The following classes could not be instantiated:
– android.support.v7.widget.RecyclerView (Open Class, Show Exception, Clear Cache)

Tip: Use View.isInEditMode() in your custom views to skip code or show sample data when shown in the IDE Exception Details java.lang.UnsupportedOperationException: Unsupported Service: accessibility   at com.android.layoutlib.bridge.android.BridgeContext.getSystemService(BridgeContext.java:463) Copy stack to clipboard

que debo hacer? ayuda, por favor. De ante mano muchas gracias

Responder
Rodry Vazquez 21/01/2016 - 19:26

Muy buen tutorial!!

Responder
Manuel 26/01/2016 - 10:49

A ver si puede alguién explicarme, por favor, ésta línea:

extends RecyclerView.Adapter

No entiendo qué significa la expresión entre los símbolos . La clase extiende de RecyclerView.Adapter… ¿Y de una clase propia interna?.

No sé qué nombre recibe esa práctica de usar , por lo que me está costando mucho encontrar información en internet.

Responder
Manuel 26/01/2016 - 10:51

Bueno, los símbolos son el mayor que y el menor que. No los pone el editor de texto. La expresión que no entiendo es:

extends RecyclerView.Adapter(menor que)AdaptadorTitulares.TitularesViewHolder(mayor que)

Responder
Sergi 27/01/2016 - 13:06

Muchas Gracias, me ha servido de mucho!

Solo quería decir que el getChildPosition está deprecated, se tiene que usar getChildAdapterPosition

Gracias!

Responder
Carlos Blanco 24/02/2016 - 17:46

Excelente tutorial, solo me queda una duda la cual estoy intentando realisar, de por si el ReciclerView posee un scroll automatico, si quisiera colocar un NestedScroller luego un relativelayout en en cual tenga un encabezado cualsea y luego tenga el componente reciclerview pero no kiero q funcione el scroll del recicler si no el del nestedscroller como haria? es decir al hacer scroll q baje tanto el encabezado como los item del scroll haciendo como q todo es un solo componente

Responder
Laura 26/02/2016 - 12:22

Como puedo hacer para que cuando haga clic en un elemento se me abra una nueva activitad, i ponga Titulo 1 i Subitiuto 1 en grande.

Pero para cada elemento o sea clic al elemento 1 i en la nueva activitat Titulo1 i Subitiulo1, clic en el item 30 i en la nueva activitat Titulo30 i Subtitulo30.

Responder
Mario German 08/03/2016 - 15:33

Hola muy buen vídeo gracias por compartir tu conocimiento me podrías ayudar, quiero que antes de crear el recyclerview este sea llamado de dos botones diferentes laboratorio y clínica y por ende me traiga solo la información correspondiente de laboratorio y clínica, me podrías indicar cómo sería el proceso. Gracias y quedo atento a tu respuesta.

Responder
Alejandro Zalazar 30/03/2016 - 2:24

Hola!, muy buen artículo. ¿Es posible que el GridLayoutManager no ajuste cada item y así se logre generar un scroll horizontal? , estoy intentando que el RecycleView me quede similar a una tabla, y que las «columnas» que no entren en el width no se posicionen debajo sino que se genere scroll horizontal.

Responder
Nathalia 26/06/2016 - 21:07

Excelente, muy buenos tutoriales, m7chas gracias!

Responder
Joaquín 24/10/2016 - 12:28

Tutorial claro y bueno, pero al aplicarlo tengo una duda que no se como resolverla y tiene que ver con el tutorial.
En View itemView = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.listitem_titular, viewGroup, false);
¿Cómo puedo acceder a un elemento de listitem_titular desde otra clase que en mi caso extiende de fragment? Con:
layNoComents= (LinearLayout) view.findViewById(R.id.comentesNoVisibles);
layNoComents.setVisibility(View.VISIBLE);
O con: getFragmentManager().findFragmentById(R.id.frgVerComentario).getView().findViewById(R.id.comentesNoVisibles).setVisibility(View.VISIBLE);
Me da el error: NullPointerException.
Si puedes orientarme te lo agradecería mucho, pues le estoy dando muchas vueltas y no doy con la solución.

Responder
Firebase para Android: Base de Datos en Tiempo Real (3) | sgoliver.net 21/11/2016 - 19:45

[…] parte del curso tenéis disponibles varios artículos sobre cómo utilizar los controles ListView y RecyclerView. Aunque no sería excesivamente complicado hacerlo de esta forma, afortunadamente Firebase nos […]

Responder
Alvaro 23/05/2017 - 15:26

getChildPosition is deprecated for Android (fuera de uso) we can use getChildAdapterPosition(View) or getChildLayoutPosition(View), also can use this: int position = getAdapterPosition();

Responder
Luis Rene Mas Mas 22/08/2017 - 1:25

Buenas noches, gracias por tu gran aporte este tutorial se asemeja mucho a lo que deseo hacer, pero te cuento mi problema espero que me ayudes.

yo guardo los datos en SQLite desde activity B y mi formulario esta cargado desde un fragment, el problema es que cuando guardo, elimino desde la activity B, al regresar a la activity A no carga el dato agregado a mi recyclerView o no se elimina el ítem.

Por favor si pudiera darme un alcance como podría hacerlo lo agradecería mucho hasta pronto, espero su respuesta.

Responder
Alex 31/03/2020 - 12:59

Hola amigo tengo un problema como hago para que un solo recyclerview me muestre dos consulta diferentes de la BD, osea la primera vez se llena con todos los curso, y la otra quiero que se llene con los cursos favoritos. E duplicado el adaptador y el viewholde. Estoy frustrado me pueden orientar.gracias

Responder
Luis 16/06/2020 - 0:24

Hola, muy claro el tuto, la app luego de ejecutar el recView.adapter = adaptador se detiene indicando que el RecyclerView se ha detenido,.
Estoy ejecutando la aplicación en un celu con Adroid 5.1.1 con el siguiente gradle:
apply plugin: ‘com.android.application’
apply plugin: ‘kotlin-android’
apply plugin: ‘kotlin-android-extensions’

android {
compileSdkVersion 29
buildToolsVersion «29.0.3»

defaultConfig {
applicationId «com.example.recyclerview»
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName «1.0»

testInstrumentationRunner «androidx.test.runner.AndroidJUnitRunner»
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile(‘proguard-android-optimize.txt’), ‘proguard-rules.pro’
}
}
}

dependencies {
implementation fileTree(dir: «libs», include: [«*.jar»])
implementation «org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version»
implementation ‘androidx.core:core-ktx:1.3.0’
implementation ‘androidx.appcompat:appcompat:1.1.0’
implementation ‘androidx.constraintlayout:constraintlayout:1.1.3’
implementation «androidx.recyclerview:recyclerview:1.1.0»
//testImplementation ‘junit:junit:4.12’
//androidTestImplementation ‘androidx.test.ext:junit:1.1.1’
//androidTestImplementation ‘androidx.test.espresso:espresso-core:3.2.0’

}

Responder
Interfaz de usuario en Android: Fragments | sgoliver.net 09/07/2020 - 19:15

[…] para mostrar dos campos por fila («De» y «Asunto»). Ya describimos cómo hacer esto en el artículo dedicado al control RecyclerView. El código de este adaptador será totalmente análogo al que ya vimos en el artículo […]

Responder
felix 16/09/2020 - 11:26

buen tutorial, tengo algunas dificultades con recycler en mi proyecto necesito pintar dos items distintos de un mismo objeto osea 2 valores del mismo objeto que tienen el mismo id

relationsArray.add(Relationship(1, «Nieto», «Nieta», «Abuelo», «Abuela»))

relationsArray.add(Relationship(2, «Hijo», «Hija», «Padre», «Madre»))

relationsArray.add(Relationship(3, «Cuidador», «Cuidadora», «Abuelo», «Abuela»))

de este array de objetos necesito sacar un item para la posicion 1 y otro para la posicion 2 del array para poder pasar el id

Responder

Dejar un comentario

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información. Aceptar Más Información

Política de Privacidad y Cookies