Inicio Android Controles de selección (V): RecyclerView

Controles de selección (V): RecyclerView

por admin

Con la llegada de Android 5.0, Google ha incorporado al SDK de Android un nuevo componente que viene a mejorar a los clásicos ListViewGridView existentes desde hace tiempo. Probablemente no sólo venga a mejorarlos sino también a sustituirlos en la mayoría de ocasiones ya que aporta flexibilidad de sobra para suplir la funcionalidad de ambos controles e ir incluso más allá.

Este nuevo control se llama RecyclerView y, al igual que conseguímos con ListView y GridView, nos va a permitir mostrar en pantalla colecciones grandes 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

Los dos primeros componentes deberíais ya reconocerlos si habéis revisado los capítulos anteriores del curso dedicados a los controles de selección. De igual forma que hemos hecho con los componentes anteriores, 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 nos «obligará» en cierta medida a utilizar el patrón View Holder que ya describimos en el segundo artículo sobre ListView, y de ahí la necesidad del segundo componente de la lista anterior, RecyclerView.ViewHolder.

Los tres siguientes 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 tres LayoutManager para las tres representaciones más habituales: 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 del nuevo 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.

En el resto del artículo voy a intentar describir de forma más o menos detallada cómo crear una aplicación de ejemplo análoga a la creada en el capítulo sobre ListView, pero utilizando en esta ocasión el nuevo componente RecyclerView.

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 recyclerview-v7, lo que nos permitirá el uso del componente RecyclerView en la aplicación:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.android.support:recyclerview-v7:+'
}

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

<android.support.v7.widget.RecyclerView
    android:id="@+id/RecView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Como siguiente paso 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.

Un par de anotaciones antes de seguir. En primer lugar, para nuestra aplicación de ejemplo utilizaré como fuente de datos una lista (ArrayList) de objetos de tipo Titular, la misma clase que ya utilizamos en el capítulo sobre el control ListView. En segundo lugar, la representación de los datos que queremos lograr será también la misma que conseguimos en aquel ejemplo, es decir, cada elemento de la lista consistirá en dos líneas sencillas de texto donde mostraremos el título y subtítulo de cada objeto Titular. Por tanto, tanto la clase Titular, como el layout asociado a los elementos de la lista (fichero listitem_titular.xml) podéis copiarlos directamente de dicho proyecto.

Como ya dijimos, la clase RecyclerView.Adapter nos obligará a hacer uso del patrón ViewHolder (recomiendo leer el artículo donde explicamos la utilidad de este patrón). Por tanto, para poder seguir con la implementación del adaptador debemos definir primero 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.

public class AdaptadorTitulares
        extends RecyclerView.Adapter<AdaptadorTitulares.TitularesViewHolder> {

    //...

    public static class TitularesViewHolder
            extends RecyclerView.ViewHolder {

        private TextView txtTitulo;
        private TextView txtSubtitulo;

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

            txtTitulo = (TextView)itemView.findViewById(R.id.LblTitulo);
            txtSubtitulo = (TextView)itemView.findViewById(R.id.LblSubTitulo);
        }

        public void bindTitular(Titular t) {
            txtTitulo.setText(t.getTitulo());
            txtSubtitulo.setText(t.getSubtitulo());
        }
    }

    //...
}

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 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 de la lista de datos.

public class AdaptadorTitulares
        extends RecyclerView.Adapter<AdaptadorTitulares.TitularesViewHolder> {

    private ArrayList<Titular> datos;

    //... 

    public AdaptadorTitulares(ArrayList<Titular> datos) {
        this.datos = datos;
    }

    @Override
    public TitularesViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

        View itemView = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.listitem_titular, viewGroup, false);

        TitularesViewHolder tvh = new TitularesViewHolder(itemView);

        return tvh;
    }

    @Override
    public void onBindViewHolder(TitularesViewHolder viewHolder, int pos) {
        Titular item = datos.get(pos);

        viewHolder.bindTitular(item);
    }

    @Override
    public int getItemCount() {
        return datos.size();
    }

    //...
}

Con esto tendríamos finalizado el adaptador, por lo que ya podríamos asignarlo al RecyclerView en nuestra actividad principal. Esto es tan sencillo como lo era en el caso de ListView/GridView, 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 setAdapter().

public class MainActivity extends ActionBarActivity {

    private RecyclerView recView;

    private ArrayList<Titular> datos;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //inicialización de la lista de datos de ejemplo
        datos = new ArrayList<Titular>();
        for(int i=0; i<50; i++)
            datos.add(new Titular("Título " + i, "Subtítulo item " + i));

        //Inicialización RecyclerView
        recView = (RecyclerView) findViewById(R.id.RecView);
        recView.setHasFixedSize(true);

        final AdaptadorTitulares adaptador = new AdaptadorTitulares(datos);

        recView.setAdapter(adaptador);

        //...
    }

    //...
}

Algunos comentarios más sobre el código anterior. He aprovechado el método onCreate() para inicializar la lista 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.

El siguiente paso obligatorio será asociar al RecyclerView un LayoutManager determinado, 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 asignaremos al RecyclerView mediante el método setLayoutManager(). Esto lo haremos justo después del código anterior, tras la asignación del adaptador:

//...

recView.setAdapter(adaptador);

recView.setLayoutManager(
    new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));

//...

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.

demo-recyclerview-1

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.setAdapter(adaptador);

recView.setLayoutManager(new GridLayoutManager(this,3));

//...

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

demo-recyclerview-2

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 todos la clase RecyclerView no tiene incluye un evento onItemClick() como ocurría en el caso de ListView.  Una vez más, RecyclerView delegará 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 la creación de cada nuevo ViewHolder para asignar a su vista asociada el evento onClick. Adicionalmente, para poder hacer esto desde fuera del adaptador, incluiremos el listener correspondiente como atributo del adaptador, y dentro de éste nos limitaremos a asignar el evento a la vista del nuevo ViewHolder y a lanzarlo cuando sea necesario desde el método onClick().  Creo que es más fácil verlo sobre el código:

public class AdaptadorTitulares
        extends RecyclerView.Adapter<AdaptadorTitulares.TitularesViewHolder>
        implements View.OnClickListener {

    //...
    private View.OnClickListener listener;

    @Override
    public TitularesViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View itemView = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.listitem_titular, viewGroup, false);

        itemView.setOnClickListener(this);

        TitularesViewHolder tvh = new TitularesViewHolder(itemView);

        return tvh;
    }

    //...

    public void setOnClickListener(View.OnClickListener listener) {
        this.listener = listener;
    }

    @Override
    public void onClick(View view) {
        if(listener != null)
            listener.onClick(view);
    }
}

Como vemos, nuestro adaptador implementará la interfaz OnClickListener, declarará un listener (el que podremos asignar posteriormente desde fuera del adaptador) como atributo de la clase, en el momento de crear el nuevo ViewHolder asociará el evento a la vista, y por último implementará el evento onClick, que se limitará a lanzar el mismo evento sobre el listener externo. El método adicional setOnClickListener() nos serivirá para asociar el listener real a nuestro adaptador en el momento de crearlo. Veamos cómo quedaría nuestra actividad principal con este cambio:

public class MainActivity extends ActionBarActivity {

    //...

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        //...

        recView = (RecyclerView) findViewById(R.id.RecView);
        recView.setHasFixedSize(true);

        final AdaptadorTitulares adaptador = new AdaptadorTitulares(datos);

        adaptador.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("DemoRecView", "Pulsado el elemento " + recView.getChildPosition(v));
            }
        });

        recView.setAdapter(adaptador);

        recView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));

        //...
    }
}

En este caso al pulsar sobre un elemento de la lista tan sólo escribiremos un mensaje de log indicando la posición en la lista del elemento pulsado, lo que conseguimos llamando al método getChildPosition() del RecyclerView.

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. RecyclerView no tiene ninguna propiedad divider como en el caso del ListView, por lo que dicha funcionalidad debemos suplirla con un ItemDecoration.

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. Para el caso de los separadores de lista podemos encontrar en un ejemplo del propio SDK de Android un ejemplo de ItemDecoration que lo implementa. La clase en cuestión se llama DividerItemDecoration y la incluyo en el proyecto de ejemplo de este apartado (tenéis el enlace a github al final del artículo). Si estudiamos un poco el código veremos que tendremos que extender de la clase RecyclerView.ItemDecoration e implementar sus métodos getItemOffsets() y onDraw()/onDrawOver(). El primero de ellos se encargará de definir los límites del elemento de la lista y el segundo de dibujar el elemento de personalización en sí. En el fondo no es complicado, aunque sí lleva su trabajo construirlo desde cero.

Para utilizar este componente deberemos simplemente crear el objeto y asociarlo a nuestro RecyclerView mediante addItemDecoration() en nuestra actividad principal:

public class MainActivity extends ActionBarActivity {

    //...

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        //...

        recView = (RecyclerView) findViewById(R.id.RecView);
        recView.setHasFixedSize(true);

        final AdaptadorTitulares adaptador = new AdaptadorTitulares(datos);

        adaptador.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("DemoRecView", "Pulsado el elemento " + recView.getChildPosition(v));
            }
        });

        recView.setAdapter(adaptador);

        recView.setLayoutManager(
            new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));

        recView.addItemDecoration(
                new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));

        //...
    }
}

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 el método setItemAnimator().

public class MainActivity extends ActionBarActivity {

    //...

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        //...

        recView = (RecyclerView) findViewById(R.id.RecView);
        recView.setHasFixedSize(true);

        final AdaptadorTitulares adaptador = new AdaptadorTitulares(datos);

        adaptador.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("DemoRecView", "Pulsado el elemento " + recView.getChildPosition(v));
            }
        });

        recView.setAdapter(adaptador);

        recView.setLayoutManager(
            new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));

        recView.addItemDecoration(
                new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));

        recView.setItemAnimator(new DefaultItemAnimator());

        //..
    }
}

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 = (Button)findViewById(R.id.BtnInsertar);

btnInsertar.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        datos.add(1, new Titular("Nuevo titular", "Subtitulo nuevo titular"));
        adaptador.notifyItemInserted(1);
    }
});

btnEliminar = (Button)findViewById(R.id.BtnEliminar);

btnEliminar.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        datos.remove(1);
        adaptador.notifyItemRemoved(1);
    }
});

btnMover = (Button)findViewById(R.id.BtnMover);

btnMover.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        Titular aux = datos.get(1);
        datos.set(1,datos.get(2));
        datos.set(2,aux);

        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.

demo-recyclerview-3

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

30 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
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

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