Cómo crear un RecyclerView anidado en Android

Un RecyclerView anidado es una implementación de un RecyclerView dentro de un RecyclerView. Un ejemplo de un diseño de este tipo se puede ver en una variedad de aplicaciones, como Play Store, donde el RecyclerView externo (principal) tiene una orientación vertical, mientras que el RecyclerView interno (secundario) tiene una orientación horizontal. Aquí se desarrolla un diseño similar.
Enfoque:  
Paso 1: Agregue las dependencias requeridas 
Agregue las siguientes dependencias al archivo build.gradle (:app) . La primera dependencia correspondiente a RecyclerView es obligatoria y la segunda es para CardView, por lo que es opcional según los requisitos de la interfaz de usuario. Dado que aquí CardView se usa en el diseño secundario de RecyclerView, se agrega la dependencia de CardView. 
Nota: Después de agregar las dependencias, haga clic en Sincronizar ahora.
 

implementación ‘androidx.recyclerview:recyclerview:1.0.0’ 
implementación ‘androidx.cardview:cardview:1.0.0’

 
Nota: para ver las versiones correctas de las dependencias, consulte aquí
Paso 2: implementar el RecyclerView 
principal El RecyclerView principal se implementa en el archivo activity_main . Aquí, el archivo activity_main solo contiene el RecyclerView principal, pero se puede personalizar según los requisitos.
 

activity_main

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <!-- This is the parent RecyclerView-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/parent_recyclerview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.271" />
  
</androidx.constraintlayout.widget.ConstraintLayout>

Paso 3: Cree un diseño de elemento para el RecyclerView principal 
Identifique los requisitos para el diseño principal y agregue las Vistas correspondientes a ellos en un archivo de diseño XML. Aquí, los archivos de diseño se nombran como parent_item . Además del RecyclerView secundario, se incluye un TextView para el título. 
 

parent_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
  
    <!--Title-->
  
    <TextView
        android:id="@+id/parent_item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="12sp"
        android:textSize="18sp"
        />
  
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="12dp"
            android:orientation="horizontal">
  
            <!--Child RecyclerView-->
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/child_recyclerview"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
        </LinearLayout>
  
  
</LinearLayout>

Paso 4: Crear un diseño de elementos para el RecyclerView secundario 
El diseño de los elementos del RecyclerView secundario se crea en un archivo de diseño XML denominado child_item . Child RecyclerView incluye un ImageView y un TextView, ambos envueltos dentro de un CardView. 
La siguiente imagen se usa como recurso de ImageView, por lo que se agrega a la carpeta de recursos dibujables  .
 

icono

child_item

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
  
    <!--CardView that holds the elements
        of the child RecyclerView -->
    <androidx.cardview.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="12dp">
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
  
            <!--Image in the CardView-->
            <!--Here we have already given
                the source for the ImageView
                and we will not assign it
                in the Java code-->
            <!--So all the ImageViews will
                hold the same image-->
            <ImageView
                android:id="@+id/img_child_item"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_marginStart="5dp"
                android:background="@color/colorPrimaryDark"
                android:src="@drawable/icon"/>
  
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="60dp"
                android:layout_toEndOf="@id/img_child_item"
                android:padding="12dp"
                android:layout_below="@+id/img_child_item"
                android:layout_alignParentStart="true"
                android:orientation="vertical">
  
                <!--Text in the CardView-->
                <TextView
                    android:id="@+id/child_item_title"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textStyle="bold"
                    />
            </LinearLayout>
        </RelativeLayout>
    </androidx.cardview.widget.CardView>
  
</FrameLayout>

Paso 5: Cree clases de elementos para cada uno de los RecyclerViews.  
Se requiere una clase Java para cada RecyclerView en la que el constructor inicializa los parámetros del elemento y se declaran los métodos getter y setter. Por lo tanto, cree las siguientes clases de Java: 
 

  • ChildItem: esta clase implementará los métodos constructor, getter y setter para las vistas del diseño child_item que deseamos configurar dinámicamente.
  • ParentItem: esta clase implementará los métodos constructor, getter y setter para las vistas del diseño parent_item que deseamos configurar dinámicamente.

ChildItem

package com.example.nestedrecyclerview;
  
public class ChildItem {
  
    // Declaration of the variable
    private String ChildItemTitle;
  
    // Constructor of the class
    // to initialize the variable*
    public ChildItem(String childItemTitle)
    {
        this.ChildItemTitle = childItemTitle;
    }
  
    // Getter and Setter method
    // for the parameter
    public String getChildItemTitle()
    {
        return ChildItemTitle;
    }
  
    public void setChildItemTitle(
        String childItemTitle)
    {
        ChildItemTitle = childItemTitle;
    }
}

ParentItem

package com.example.nestedrecyclerview;
  
import java.util.List;
  
public class ParentItem {
  
    // Declaration of the variables
    private String ParentItemTitle;
    private List<ChildItem> ChildItemList;
  
    // Constructor of the class
    // to initialize the variables
    public ParentItem(
        String ParentItemTitle,
        List<ChildItem> ChildItemList)
    {
  
        this.ParentItemTitle = ParentItemTitle;
        this.ChildItemList = ChildItemList;
    }
  
    // Getter and Setter methods
    // for each parameter
    public String getParentItemTitle()
    {
        return ParentItemTitle;
    }
  
    public void setParentItemTitle(
        String parentItemTitle)
    {
        ParentItemTitle = parentItemTitle;
    }
  
    public List<ChildItem> getChildItemList()
    {
        return ChildItemList;
    }
  
    public void setChildItemList(
        List<ChildItem> childItemList)
    {
        ChildItemList = childItemList;
    }
}

Paso 6: cree una clase de adaptador para cada uno de los RecyclerViews.  
Se requiere una clase de adaptador para pasar los datos que se mostrarán en las vistas de RecyclerView. 
Se necesita una clase de adaptador para las clases ChildItem y ParentItem.
 

  • ChildAdapter: esta es la clase de adaptador para contener la información que se mostrará en las vistas de la clase ChildItem.
  • ParentAdapter: esta es la clase de adaptador para contener la información que se mostrará en las vistas de la clase ParentItem.

En la clase ParentItemAdapter, se crea una instancia de la clase
 

RecyclerView.RecycledViewPool

Esta clase se usa para pasar Vistas entre el RecyclerView principal y el RecyclerView secundario. 
 

ChildItemAdapter

package com.example.nestedrecyclerview;
  
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
  
import java.util.List;
  
public class ChildItemAdapter
    extends RecyclerView
                .Adapter<ChildItemAdapter.ChildViewHolder> {
  
    private List<ChildItem> ChildItemList;
  
    // Constructor
    ChildItemAdapter(List<ChildItem> childItemList)
    {
        this.ChildItemList = childItemList;
    }
  
    @NonNull
    @Override
    public ChildViewHolder onCreateViewHolder(
        @NonNull ViewGroup viewGroup,
        int i)
    {
  
        // Here we inflate the corresponding
        // layout of the child item
        View view = LayoutInflater
                        .from(viewGroup.getContext())
                        .inflate(
                            R.layout.child_item,
                            viewGroup, false);
  
        return new ChildViewHolder(view);
    }
  
    @Override
    public void onBindViewHolder(
        @NonNull ChildViewHolder childViewHolder,
        int position)
    {
  
        // Create an instance of the ChildItem
        // class for the given position
        ChildItem childItem
            = ChildItemList.get(position);
  
        // For the created instance, set title.
        // No need to set the image for
        // the ImageViews because we have
        // provided the source for the images
        // in the layout file itself
        childViewHolder
            .ChildItemTitle
            .setText(childItem.getChildItemTitle());
    }
  
    @Override
    public int getItemCount()
    {
  
        // This method returns the number
        // of items we have added
        // in the ChildItemList
        // i.e. the number of instances
        // of the ChildItemList
        // that have been created
        return ChildItemList.size();
    }
  
    // This class is to initialize
    // the Views present
    // in the child RecyclerView
    class ChildViewHolder
        extends RecyclerView.ViewHolder {
  
        TextView ChildItemTitle;
  
        ChildViewHolder(View itemView)
        {
            super(itemView);
            ChildItemTitle
                = itemView.findViewById(
                    R.id.child_item_title);
        }
    }
}

ParentItemAdapter

package com.example.nestedrecyclerview;
  
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
  
import java.util.List;
  
public class ParentItemAdapter
    extends RecyclerView
                .Adapter<ParentItemAdapter.ParentViewHolder> {
  
    // An object of RecyclerView.RecycledViewPool
    // is created to share the Views
    // between the child and
    // the parent RecyclerViews
    private RecyclerView.RecycledViewPool
        viewPool
        = new RecyclerView
              .RecycledViewPool();
    private List<ParentItem> itemList;
  
    ParentItemAdapter(List<ParentItem> itemList)
    {
        this.itemList = itemList;
    }
  
    @NonNull
    @Override
    public ParentViewHolder onCreateViewHolder(
        @NonNull ViewGroup viewGroup,
        int i)
    {
  
        // Here we inflate the corresponding
        // layout of the parent item
        View view = LayoutInflater
                        .from(viewGroup.getContext())
                        .inflate(
                            R.layout.parent_item,
                            viewGroup, false);
  
        return new ParentViewHolder(view);
    }
  
    @Override
    public void onBindViewHolder(
        @NonNull ParentViewHolder parentViewHolder,
        int position)
    {
  
        // Create an instance of the ParentItem
        // class for the given position
        ParentItem parentItem
            = itemList.get(position);
  
        // For the created instance,
        // get the title and set it
        // as the text for the TextView
        parentViewHolder
            .ParentItemTitle
            .setText(parentItem.getParentItemTitle());
  
        // Create a layout manager
        // to assign a layout
        // to the RecyclerView.
  
        // Here we have assigned the layout
        // as LinearLayout with vertical orientation
        LinearLayoutManager layoutManager
            = new LinearLayoutManager(
                parentViewHolder
                    .ChildRecyclerView
                    .getContext(),
                LinearLayoutManager.HORIZONTAL,
                false);
  
        // Since this is a nested layout, so
        // to define how many child items
        // should be prefetched when the
        // child RecyclerView is nested
        // inside the parent RecyclerView,
        // we use the following method
        layoutManager
            .setInitialPrefetchItemCount(
                parentItem
                    .getChildItemList()
                    .size());
  
        // Create an instance of the child
        // item view adapter and set its
        // adapter, layout manager and RecyclerViewPool
        ChildItemAdapter childItemAdapter
            = new ChildItemAdapter(
                parentItem
                    .getChildItemList());
        parentViewHolder
            .ChildRecyclerView
            .setLayoutManager(layoutManager);
        parentViewHolder
            .ChildRecyclerView
            .setAdapter(childItemAdapter);
        parentViewHolder
            .ChildRecyclerView
            .setRecycledViewPool(viewPool);
    }
  
    // This method returns the number
    // of items we have added in the
    // ParentItemList i.e. the number
    // of instances we have created
    // of the ParentItemList
    @Override
    public int getItemCount()
    {
  
        return itemList.size();
    }
  
    // This class is to initialize
    // the Views present in
    // the parent RecyclerView
    class ParentViewHolder
        extends RecyclerView.ViewHolder {
  
        private TextView ParentItemTitle;
        private RecyclerView ChildRecyclerView;
  
        ParentViewHolder(final View itemView)
        {
            super(itemView);
  
            ParentItemTitle
                = itemView
                      .findViewById(
                          R.id.parent_item_title);
            ChildRecyclerView
                = itemView
                      .findViewById(
                          R.id.child_recyclerview);
        }
    }
}

Paso 7: establezca el diseño del RecyclerView principal y pase los argumentos a ambos RecyclerViews. Los argumentos que se pasan a RecyclerViews se proporcionan en la clase Java que infla la actividad del RecyclerView principal (aquí, actividad_principal). Así que aquí los argumentos se pasarán en el archivo MainActivity. 
Además, establezca el diseño para el RecyclerView padre aquí mismo.
 

MainActivity

package com.example.nestedrecyclerview;
  
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
  
import java.util.ArrayList;
import java.util.List;
  
public class MainActivity
    extends AppCompatActivity {
  
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
  
        RecyclerView
            ParentRecyclerViewItem
            = findViewById(
                R.id.parent_recyclerview);
  
        // Initialise the Linear layout manager
        LinearLayoutManager
            layoutManager
            = new LinearLayoutManager(
                MainActivity.this);
  
        // Pass the arguments
        // to the parentItemAdapter.
        // These arguments are passed
        // using a method ParentItemList()
        ParentItemAdapter
            parentItemAdapter
            = new ParentItemAdapter(
                ParentItemList());
  
        // Set the layout manager
        // and adapter for items
        // of the parent recyclerview
        ParentRecyclerViewItem
            .setAdapter(parentItemAdapter);
        ParentRecyclerViewItem
            .setLayoutManager(layoutManager);
    }
  
    private List<ParentItem> ParentItemList()
    {
        List<ParentItem> itemList
            = new ArrayList<>();
  
        ParentItem item
            = new ParentItem(
                "Title 1",
                ChildItemList());
        itemList.add(item);
        ParentItem item1
            = new ParentItem(
                "Title 2",
                ChildItemList());
        itemList.add(item1);
        ParentItem item2
            = new ParentItem(
                "Title 3",
                ChildItemList());
        itemList.add(item2);
        ParentItem item3
            = new ParentItem(
                "Title 4",
                ChildItemList());
        itemList.add(item3);
  
        return itemList;
    }
  
    // Method to pass the arguments
    // for the elements
    // of child RecyclerView
    private List<ChildItem> ChildItemList()
    {
        List<ChildItem> ChildItemList
            = new ArrayList<>();
  
        ChildItemList.add(new ChildItem("Card 1"));
        ChildItemList.add(new ChildItem("Card 2"));
        ChildItemList.add(new ChildItem("Card 3"));
        ChildItemList.add(new ChildItem("Card 4"));
  
        return ChildItemList;
    }
}

Producción: 
 

Publicación traducida automáticamente

Artículo escrito por aayushitated2000 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *