RecyclerView Básico y Avanzado en Android

RecyclerView Básico y Avanzado en Android

Hola amigos 👋 Bienvenidos a un nuevo tutorial de Universo Android. Hoy aprenderemos a dominar RecyclerView, el componente más poderoso y eficiente para mostrar listas de datos en Android, desde lo básico hasta técnicas avanzadas.

Al finalizar este tutorial tendrás una aplicación que incluirá:

  • RecyclerView básico con datos simples
  • ViewHolder pattern optimizado
  • Adaptadores personalizados
  • Click listeners en elementos
  • Diferentes tipos de Layout Manager
  • Múltiples tipos de vista
  • Animaciones y decoraciones
  • Carga infinita (Infinite Scroll)

🟩 1. ¿Qué es RecyclerView?

RecyclerView es un componente avanzado para mostrar grandes conjuntos de datos de forma eficiente. Reutiliza las vistas que salen de pantalla para mostrar nuevos datos, optimizando memoria y rendimiento.

🟩 2. Ventajas sobre ListView

  • Reutilización automática de vistas (ViewHolder obligatorio)
  • Mejor rendimiento con listas grandes
  • Soporte para animaciones integradas
  • Múltiples Layout Managers (Lista, Grid, Staggered)
  • Más flexible y personalizable

🟩 3. Crear el Proyecto en Android Studio

Creamos un nuevo proyecto en Android Studio con Empty Activity.

🟩 4. Agregar Dependencias

Abre build.gradle (Module: app):

dependencies {
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.9.0'
    implementation 'androidx.recyclerview:recyclerview:1.3.2'
    implementation 'androidx.cardview:cardview:1.0.0'
}

🟩 5. Diseño XML Principal

📄 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="RecyclerView Demo"
        android:textSize="24sp"
        android:textStyle="bold"
        android:textColor="#2196F3"
        android:layout_marginBottom="16dp" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />

</LinearLayout>

🟩 6. Layout del Item

📄 res/layout/item_simple.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    app:cardCornerRadius="8dp"
    app:cardElevation="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="16dp">

        <ImageView
            android:id="@+id/imgIcon"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:src="@android:drawable/ic_dialog_info"
            android:background="@drawable/circle_background" />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:layout_marginLeft="16dp"
            android:layout_gravity="center_vertical">

            <TextView
                android:id="@+id/txtTitle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Título"
                android:textSize="18sp"
                android:textStyle="bold"
                android:textColor="#000000" />

            <TextView
                android:id="@+id/txtDescription"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Descripción"
                android:textSize="14sp"
                android:textColor="#666666"
                android:layout_marginTop="4dp" />

        </LinearLayout>

    </LinearLayout>

</androidx.cardview.widget.CardView>

🟩 7. Crear Drawable Circular

📄 res/drawable/circle_background.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#E3F2FD" />
    <size android:width="60dp" android:height="60dp" />
</shape>

🟩 8. Clase Modelo

📄 Item.java

public class Item {
    private String title;
    private String description;
    private int iconResource;

    public Item(String title, String description, int iconResource) {
        this.title = title;
        this.description = description;
        this.iconResource = iconResource;
    }

    public String getTitle() { return title; }
    public String getDescription() { return description; }
    public int getIconResource() { return iconResource; }

    public void setTitle(String title) { this.title = title; }
    public void setDescription(String description) { this.description = description; }
    public void setIconResource(int iconResource) { this.iconResource = iconResource; }
}

🟩 9. Adaptador Básico

📄 SimpleAdapter.java

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;

public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.ViewHolder> {

    private ArrayList<Item> items;
    private OnItemClickListener listener;

    public interface OnItemClickListener {
        void onItemClick(Item item, int position);
    }

    public SimpleAdapter(ArrayList<Item> items, OnItemClickListener listener) {
        this.items = items;
        this.listener = listener;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_simple, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Item item = items.get(position);
        holder.bind(item, listener);
    }

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

    static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView imgIcon;
        TextView txtTitle, txtDescription;

        ViewHolder(View itemView) {
            super(itemView);
            imgIcon = itemView.findViewById(R.id.imgIcon);
            txtTitle = itemView.findViewById(R.id.txtTitle);
            txtDescription = itemView.findViewById(R.id.txtDescription);
        }

        void bind(Item item, OnItemClickListener listener) {
            txtTitle.setText(item.getTitle());
            txtDescription.setText(item.getDescription());
            imgIcon.setImageResource(item.getIconResource());

            itemView.setOnClickListener(v -> 
                listener.onItemClick(item, getAdapterPosition())
            );
        }
    }
}

🟩 10. MainActivity Básica

📄 MainActivity.java

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.widget.Toast;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    SimpleAdapter adapter;
    ArrayList<Item> items;

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

        recyclerView = findViewById(R.id.recyclerView);
        
        createData();
        setupRecyclerView();
    }

    private void createData() {
        items = new ArrayList<>();
        items.add(new Item("Android Studio", "IDE oficial de Android", android.R.drawable.ic_menu_info_details));
        items.add(new Item("Java", "Lenguaje de programación", android.R.drawable.ic_menu_edit));
        items.add(new Item("Kotlin", "Lenguaje moderno", android.R.drawable.ic_menu_manage));
        items.add(new Item("Firebase", "Backend as a Service", android.R.drawable.ic_menu_upload));
        items.add(new Item("Material Design", "Sistema de diseño", android.R.drawable.ic_menu_gallery));
        items.add(new Item("Gradle", "Sistema de compilación", android.R.drawable.ic_menu_preferences));
        items.add(new Item("Git", "Control de versiones", android.R.drawable.ic_menu_share));
        items.add(new Item("XML", "Lenguaje de marcado", android.R.drawable.ic_menu_view));
    }

    private void setupRecyclerView() {
        adapter = new SimpleAdapter(items, (item, position) -> 
            Toast.makeText(this, "Clickeado: " + item.getTitle(), Toast.LENGTH_SHORT).show()
        );
        
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
    }
}

🟩 11. Layout Managers

// LinearLayoutManager (Lista vertical)
recyclerView.setLayoutManager(new LinearLayoutManager(this));

// LinearLayoutManager (Lista horizontal)
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));

// GridLayoutManager (Cuadrícula)
recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); // 2 columnas

// StaggeredGridLayoutManager (Cuadrícula irregular)
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));

🟩 12. Adaptador con Múltiples Tipos de Vista

📄 MultiTypeAdapter.java

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;

public class MultiTypeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;

    private ArrayList<Object> items;

    public MultiTypeAdapter(ArrayList<Object> items) {
        this.items = items;
    }

    @Override
    public int getItemViewType(int position) {
        Object item = items.get(position);
        if (item instanceof String) {
            return TYPE_HEADER;
        } else {
            return TYPE_ITEM;
        }
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == TYPE_HEADER) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(android.R.layout.simple_list_item_1, parent, false);
            return new HeaderViewHolder(view);
        } else {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_simple, parent, false);
            return new ItemViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof HeaderViewHolder) {
            String header = (String) items.get(position);
            ((HeaderViewHolder) holder).bind(header);
        } else if (holder instanceof ItemViewHolder) {
            Item item = (Item) items.get(position);
            ((ItemViewHolder) holder).bind(item);
        }
    }

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

    static class HeaderViewHolder extends RecyclerView.ViewHolder {
        TextView txtHeader;

        HeaderViewHolder(View itemView) {
            super(itemView);
            txtHeader = itemView.findViewById(android.R.id.text1);
        }

        void bind(String header) {
            txtHeader.setText(header);
            txtHeader.setTextSize(20);
            txtHeader.setTextColor(0xFF2196F3);
        }
    }

    static class ItemViewHolder extends RecyclerView.ViewHolder {
        TextView txtTitle, txtDescription;

        ItemViewHolder(View itemView) {
            super(itemView);
            txtTitle = itemView.findViewById(R.id.txtTitle);
            txtDescription = itemView.findViewById(R.id.txtDescription);
        }

        void bind(Item item) {
            txtTitle.setText(item.getTitle());
            txtDescription.setText(item.getDescription());
        }
    }
}

🟩 13. Animaciones

// En el adaptador
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    Item item = items.get(position);
    holder.bind(item, listener);
    
    // Animación de entrada
    holder.itemView.setAlpha(0f);
    holder.itemView.animate()
        .alpha(1f)
        .setDuration(300)
        .start();
}

🟩 14. Métodos Útiles

MétodoDescripción
notifyDataSetChanged()Actualiza toda la lista
notifyItemInserted(position)Notifica inserción
notifyItemRemoved(position)Notifica eliminación
notifyItemChanged(position)Notifica cambio
setHasFixedSize(true)Optimiza si el tamaño es fijo
addItemDecoration()Agrega decoraciones

▶️ Cómo Ejecutar

  1. Abre Android Studio
  2. Presiona Run
  3. Verás el RecyclerView funcionando con datos

🧪 Resultado Final

Tu aplicación mostrará una lista eficiente con RecyclerView, click listeners, diferentes layout managers y animaciones.

📥 Descargar Proyecto

👉

🙌 Gracias por Visitar mi Blog

✔️ Compártelo
✔️ Déjame un comentario
✔️ Sígueme para más contenido

❓ Preguntas Frecuentes

1. ¿Cuál es la diferencia entre RecyclerView y ListView?
RecyclerView es más eficiente, reutiliza vistas automáticamente y soporta múltiples layout managers.

2. ¿Qué es el ViewHolder pattern?
Es un patrón que guarda referencias a las vistas para evitar llamadas repetidas a findViewById().

3. ¿Puedo tener diferentes tipos de elementos?
Sí, usando getItemViewType() para retornar diferentes tipos de vista.

4. ¿Cómo agrego un click listener?
Implementa una interface OnItemClickListener y configúrala en el ViewHolder.

No hay comentarios:

Publicar un comentario