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 objetosViewHolder
necesarios para los elementos de la colección.onBindViewHolder()
. Encargado de actualizar los datos de unViewHolder
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.
34 comentarios
¡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í!
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
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
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???
Qué bueno!!! Muy bien explicado.
Gracias :)
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!!
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
Muy buenos tutoriales! gracias por tomarte el tiempo. :)
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?
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.
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.
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.
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.
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
[…] 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. […]
[…] http://www.sgoliver.net […]
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
Muy buen tutorial!!
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.
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)
Muchas Gracias, me ha servido de mucho!
Solo quería decir que el getChildPosition está deprecated, se tiene que usar getChildAdapterPosition
Gracias!
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
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.
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.
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.
Excelente, muy buenos tutoriales, m7chas gracias!
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.
[…] 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 […]
getChildPosition is deprecated for Android (fuera de uso) we can use getChildAdapterPosition(View) or getChildLayoutPosition(View), also can use this: int position = getAdapterPosition();
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.
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
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’
}
[…] 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 […]
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