¿Cómo crear RecyclerView con Multiple ViewType en Android?

RecyclerView forma una parte muy importante de la interfaz de usuario en el desarrollo de aplicaciones de Android . Es especialmente importante optimizar el consumo de memoria durante la visualización de una larga lista de elementos. Un RecylerView infla una lista personalizada de elementos. Esta lista puede tener todos los diseños similares o varios diseños distintos. Aquí, se desarrolla un RecyclerView de este tipo con múltiples ViewTypes. El siguiente es un ejemplo de Android RecyclerView con varias vistas.
tipo de vista múltiple

Acercarse

Paso 1: agregue las dependencias requeridas
Cree un nuevo proyecto en Android Studio y agregue las siguientes dependencias en build.gradle(:app) en la sección Gradle Scripts:

implementación “androidx.recyclerview:recyclerview:1.1.0”
implementación “androidx.cardview:cardview:1.0.0”

Para obtener versiones más actualizadas de las dependencias, haga clic aquí . Si bien la primera dependencia es obligatoria, la segunda es opcional según los requisitos de la interfaz de usuario. Haga clic en Sincronizar ahora y continúe.

Paso 2: implementar RecyclerView en activity_main.xml

Cree un diseño que contenga el RecyclerView principal. Aquí, se ha creado en el archivo activity_main.xml . El diseño dado contiene simplemente un Welcome TextView y un RecyclerView, sin embargo, se puede personalizar según los requisitos. El código para activity_main.xml se proporciona a continuación.

activity_main.xml

<?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">
  
    <!--Welcome text-->
    <TextView
        android:id="@+id/heading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Welcome to GFG!"
        android:textColor="#006600"
        android:textSize="20dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.058"></TextView>
  
    <!-- Main RecyclerView-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:layout_marginStart="15dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/heading"
        app:layout_constraintVertical_bias="0.061"
        android:paddingBottom="100dp"/>
  
</androidx.constraintlayout.widget.ConstraintLayout>

Paso 3: agregue el archivo dibujable requerido

Antes de continuar, asegúrese de que todos los recursos extraíbles necesarios se agreguen en el directorio de recursos extraíbles . En este tutorial, solo se ha utilizado el siguiente icono:
icono_dos

Paso 4: Cree todos los diseños de elementos

Identifique todos los diferentes diseños que RecyclerView debe contener e impleméntelos en archivos XML separados en el directorio de recursos de diseño. Aquí, se han creado dos diseños distintos. El primero se implementa en layout_one.xml mientras que el segundo en layout_two.xml. El primer diseño consiste en solo un TextView envuelto dentro de un CardView. A continuación se muestra su implementación.

layout_one.xml

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
  
    <!--parent CardView-->
    <androidx.cardview.widget.CardView
        android:id="@+id/cardview_one"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:elevation="5dp">
  
        <!--LinearLayout inside the CardView-->
        <!--This layout is accessed to create
            toasts when this item is clicked-->
        <LinearLayout
            android:id="@+id/linearlayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
  
            <!--This layout only holds a TextView
                inside a CardView-->
            <TextView
                android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#000000"
                android:textSize="20dp"
                android:layout_margin="20dp"/>
  
        </LinearLayout>
    </androidx.cardview.widget.CardView>
  
    <!-- This is extra space given to maintain a 
         gap between two consecutive CardViews-->
    <Space
        android:layout_width="match_parent"
        android:layout_height="10dp"/>
  
</LinearLayout>

El segundo elemento contiene tres elementos envueltos dentro de un CardView.

  • Una vista de imagen
  • Una vista de texto
  • Otro TextView con un tamaño de fuente relativamente más pequeño

layout_two.xml

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:id="@+id/linearlayout"
    >
    <!--parent CardView-->
    <androidx.cardview.widget.CardView
        android:id="@+id/cardview_two"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:elevation="5dp">
  
        <!--LinearLayout inside the CardView-->
        <!--This layout is accessed to create
             toasts when this item is clicked-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
  
            <!--This layout consists of an ImageView 
                and two TextViews-->
            <ImageView
                android:id="@+id/image"
                android:layout_width="80dp"
                android:layout_height="80dp"/>
  
            <!-- The purpose of this LinearLayout  is 
                 to align the two TextViews Vertically-->
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="vertical">
  
                <!--These are the 2 TextViews in this layout-->
                <TextView
                    android:id="@+id/text_one"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:layout_marginStart="20dp"
                    android:textColor="#000000"
                    android:textSize="20dp"/>
  
                <TextView
                    android:id="@+id/text_two"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#000000"
                    android:textSize="15dp"
                    android:layout_marginTop="10dp"
                    android:layout_marginStart="20dp"/>
  
            </LinearLayout>
        </LinearLayout>
  
    </androidx.cardview.widget.CardView>
    <!-- This is extra space given to 
         maintain a gap between two CardViews-->
    <Space
        android:layout_width="match_parent"
        android:layout_height="10dp"/>
  
</LinearLayout>

Paso 5: crea una clase de artículo

Cree una clase Java que contenga los constructores públicos correspondientes a cada diseño. Por lo tanto, se han creado dos constructores aquí en el archivo ItemClass.java . Además de los constructores, los métodos getter y setter también se declaran aquí. Esto se hace para acceder de forma segura a las variables privadas de ItemClass fuera de él. Así es como ItemClass.java busca los diseños creados anteriormente:

ItemClass.java

package com.example.android.multilayoutrecyclerview;
  
// ItemClass
  
public class ItemClass {
  
    // Integers assigned to each layout
    // these are declared static so that they can
    // be accessed from the class name itself
    // And final so that they are not modified later
    public static final int LayoutOne = 0;
    public static final int LayoutTwo = 1;
  
    // This variable ViewType specifies
    // which out of the two layouts
    // is expected in the given item
    private int viewType;
  
    // String variable to hold the TextView
    // of the first item.
    private String text;
  
    // public constructor for the first layout
    public ItemClass(int viewType, String text)
    {
        this.text = text;
        this.viewType = viewType;
    }
  
    // getter and setter methods for the text variable
  
    public String getText() { return text; }
  
    public void setText(String text) { this.text = text; }
  
    // Variables for the item of second layout
    private int icon;
    private String text_one, text_two;
  
    // public constructor for the second layout
    public ItemClass(int viewType, int icon, String text_one,
                     String text_two)
    {
        this.icon = icon;
        this.text_one = text_one;
        this.text_two = text_two;
        this.viewType = viewType;
    }
  
    // getter and setter methods for
    // the variables of the second layout
  
    public int geticon() { return icon; }
  
    public void seticon(int icon) { this.icon = icon; }
  
    public String getText_one() { return text_one; }
  
    public void setText_one(String text_one)
    {
        this.text_one = text_one;
    }
  
    public String getText_two() { return text_two; }
  
    public void setText_two(String text_two)
    {
        this.text_two = text_two;
    }
  
    public int getViewType() { return viewType; }
  
    public void setViewType(int viewType)
    {
        this.viewType = viewType;
    }
}

Paso 6: crea la clase de adaptador

Cree una clase de adaptador para mostrar el contenido de RecyclerView. En la clase Adapter para varios ViewType RecyclerView, el siguiente método se anula además de los métodos convencionales onCreateViewHolder()y . El método es el único responsable de elegir el diseño correspondiente a cada artículo. Además de agregar un método adicional, los otros cambios incluyen la definición de una clase ViewHolder específica para cada uno de los diseños de elementos. Siga el código dado para una comprensión más profunda.onBindViewHolder()getItemCount()getItemViewType()

AdapterClass.java

package com.example.android.multilayoutrecyclerview;
  
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
  
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
  
import java.util.List;
  
import static com.example.android.multilayoutrecyclerview.ItemClass.LayoutOne;
import static com.example.android.multilayoutrecyclerview.ItemClass.LayoutTwo;
  
public class AdapterClass extends RecyclerView.Adapter {
  
    private List<ItemClass> itemClassList;
  
    // public constructor for this class
    public AdapterClass(List<ItemClass> itemClassList)
    {
        this.itemClassList = itemClassList;
    }
  
    // Override the getItemViewType method.
    // This method uses a switch statement
    // to assign the layout to each item
    // depending on the viewType passed
  
    @Override
    public int getItemViewType(int position)
    {
        switch (itemClassList.get(position).getViewType()) {
        case 0:
            return LayoutOne;
        case 1:
            return LayoutTwo;
        default:
            return -1;
        }
    }
  
    // Create classes for each layout ViewHolder.
  
    class LayoutOneViewHolder
        extends RecyclerView.ViewHolder {
  
        private TextView textview;
        private LinearLayout linearLayout;
  
        public LayoutOneViewHolder(@NonNull View itemView)
        {
            super(itemView);
  
            // Find the Views
            textview = itemView.findViewById(R.id.text);
            linearLayout
                = itemView.findViewById(R.id.linearlayout);
        }
  
        // method to set the views that will
        // be used further in onBindViewHolder method.
        private void setView(String text)
        {
  
            textview.setText(text);
        }
    }
  
    // similarly a class for the second layout is also
    // created.
  
    class LayoutTwoViewHolder
        extends RecyclerView.ViewHolder {
  
        private ImageView icon;
        private TextView text_one, text_two;
        private LinearLayout linearLayout;
  
        public LayoutTwoViewHolder(@NonNull View itemView)
        {
            super(itemView);
            icon = itemView.findViewById(R.id.image);
            text_one = itemView.findViewById(R.id.text_one);
            text_two = itemView.findViewById(R.id.text_two);
            linearLayout
                = itemView.findViewById(R.id.linearlayout);
        }
  
        private void setViews(int image, String textOne,
                              String textTwo)
        {
            icon.setImageResource(image);
            text_one.setText(textOne);
            text_two.setText(textTwo);
        }
    }
  
    // In the onCreateViewHolder, inflate the
    // xml layout as per the viewType.
    // This method returns either of the
    // ViewHolder classes defined above,
    // depending upon the layout passed as a parameter.
  
    @NonNull
    @Override
    public RecyclerView.ViewHolder
    onCreateViewHolder(@NonNull ViewGroup parent,
                       int viewType)
    {
        switch (viewType) {
        case LayoutOne:
            View layoutOne
                = LayoutInflater.from(parent.getContext())
                      .inflate(R.layout.layout_one, parent,
                               false);
            return new LayoutOneViewHolder(layoutOne);
        case LayoutTwo:
            View layoutTwo
                = LayoutInflater.from(parent.getContext())
                      .inflate(R.layout.layout_two, parent,
                               false);
            return new LayoutTwoViewHolder(layoutTwo);
        default:
            return null;
        }
    }
  
    // In onBindViewHolder, set the Views for each element
    // of the layout using the methods defined in the
    // respective ViewHolder classes.
  
    @Override
    public void onBindViewHolder(
        @NonNull RecyclerView.ViewHolder holder,
        int position)
    {
  
        switch (itemClassList.get(position).getViewType()) {
        case LayoutOne:
  
            String text
                = itemClassList.get(position).getText();
            ((LayoutOneViewHolder)holder).setView(text);
  
            // The following code pops a toast message
            // when the item layout is clicked.
            // This message indicates the corresponding
            // layout.
            ((LayoutOneViewHolder)holder)
                .linearLayout.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view)
                        {
  
                            Toast
                                .makeText(
                                    view.getContext(),
                                    "Hello from Layout One!",
                                    Toast.LENGTH_SHORT)
                                .show();
                        }
                    });
  
            break;
  
        case LayoutTwo:
            int image
                = itemClassList.get(position).geticon();
            String text_one
                = itemClassList.get(position).getText_one();
            String text_two
                = itemClassList.get(position).getText_two();
            ((LayoutTwoViewHolder)holder)
                .setViews(image, text_one, text_two);
            ((LayoutTwoViewHolder)holder)
                .linearLayout.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view)
                        {
  
                            Toast
                                .makeText(
                                    view.getContext(),
                                    "Hello from Layout Two!",
                                    Toast.LENGTH_SHORT)
                                .show();
                        }
                    });
            break;
        default:
            return;
        }
    }
  
    // This method returns the count of items present in the
    // RecyclerView at any given time.
  
    @Override
    public int getItemCount()
    {
        return itemClassList.size();
    }
}

Paso 7: Complete el archivo MainActivity.java

Las siguientes son las tareas importantes que se implementarán en el archivo MainActivity.java .

  • Establezca la vista de contenido como la actividad XML en la que se ha implementado el RecyclerView principal, aquí activity_main.xml .
  • Establezca el diseño para RecyclerView.
  • Pase argumentos a RecyclerView.
  • Configure el adaptador.

MainActivity.java

package com.example.android.multilayoutrecyclerview;
  
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
  
import android.os.Bundle;
import android.widget.Adapter;
  
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);
  
        // From the MainActivity, find the RecyclerView.
        RecyclerView recyclerView
            = findViewById(R.id.recyclerView);
  
        // Create and set the layout manager
        // For the RecyclerView.
        LinearLayoutManager layoutManager
            = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
  
        List<ItemClass> itemClasses = new ArrayList<>();
  
        // pass the arguments
        itemClasses.add(new ItemClass(ItemClass.LayoutOne,
                                      "Item Type 1"));
        itemClasses.add(new ItemClass(ItemClass.LayoutOne,
                                      "Item Type 1"));
        itemClasses.add(new ItemClass(
            ItemClass.LayoutTwo, R.drawable.icon,
            "Item Type 2", "Text"));
        itemClasses.add(new ItemClass(ItemClass.LayoutOne,
                                      "Item Type 1"));
        itemClasses.add(new ItemClass(
            ItemClass.LayoutTwo, R.drawable.icon,
            "Item Type 2", "Text"));
        itemClasses.add(new ItemClass(
            ItemClass.LayoutTwo, R.drawable.icon,
            "Item Type 2", "Text"));
        itemClasses.add(new ItemClass(ItemClass.LayoutOne,
                                      "Item Type 1"));
        itemClasses.add(new ItemClass(
            ItemClass.LayoutTwo, R.drawable.icon,
            "Item Type 2", "Text"));
        AdapterClass adapterClass
            = new AdapterClass(itemClasses);
  
        AdapterClass adapter
            = new AdapterClass(itemClasses);
  
        // set the adapter
        recyclerView.setAdapter(adapter);
    }
}

Salida: ejecutar en el emulador

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 *