如何在 Android 中创建具有多个 ViewType 的 RecyclerView?
RecyclerView 构成了 Android App 开发中 UI 的一个非常重要的部分。在显示一长串项目期间优化内存消耗尤为重要。 RecylerView 会扩充自定义的项目列表。此列表可以具有所有相似的布局或多个不同的布局。在这里,开发了这样一个具有多个ViewTypes的RecyclerView。以下是具有多个视图的 Android RecyclerView 示例。
方法
第 1 步:添加所需的依赖项
在 Android Studio 中创建一个新项目,并在 Gradle Scripts 部分下的build.gradle(:app)中添加以下依赖项:
implementation “androidx.recyclerview:recyclerview:1.1.0”
implementation “androidx.cardview:cardview:1.0.0”
有关依赖项的更多最新版本,请单击此处。虽然第一个依赖项是强制性的,但第二个依赖项是可选的,具体取决于 UI 要求。单击立即同步并继续。
第二步:在activity_main.xml中实现RecyclerView
创建一个包含主 RecyclerView 的布局。在这里,它已在activity_main.xml文件中创建。给定的布局仅包含一个 Welcome TextView 和一个 RecyclerView,但是可以根据要求对其进行自定义。 activity_main.xml的代码如下所示。
activity_main.xml
layout_one.xml
layout_two.xml
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;
}
}
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 itemClassList;
// public constructor for this class
public AdapterClass(List 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();
}
}
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 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);
}
}
第 3 步:添加所需的可绘制文件
在继续之前,请确保所有必要的可绘制资源都已添加到可绘制资源目录下。在本教程中,仅使用了以下图标:
第 4 步:创建所有项目布局
识别 RecyclerView 需要在布局资源目录下的单独 XML 文件中保存和实现它们的所有不同布局。在这里,已经创建了两个不同的布局。第一个在layout_one.xml中实现,第二个在layout_two.xml 中实现。第一个布局仅包含一个包裹在 CardView 中的 TextView。下面是它的实现。
layout_one.xml
第二项包含三个包裹在 CardView 中的元素。
- 一个图像视图
- 一个文本视图
- 另一个字体大小相对较小的 TextView
layout_two.xml
第 5 步:创建一个 Item 类
创建一个Java类,其中包含与每个布局对应的公共构造函数。因此,这里在ItemClass 中创建了两个构造函数。 Java文件。除了构造函数之外,这里还声明了 getter 和 setter 方法。这样做是为了安全地访问 ItemClass 之外的私有变量。这就是ItemClass的方式。 Java查找上面创建的布局:
项目类。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;
}
}
第 6 步:创建适配器类
创建一个适配器类来显示 RecyclerView 的内容。在多个 ViewType RecyclerView 的 Adapter 类中,除了常规的onCreateViewHolder()
、 onBindViewHolder()
和getItemCount()
方法之外,还重写了以下方法。 getItemViewType()
方法只负责选择每个项目对应的布局。除了添加一个额外的方法外,其他更改包括为每个项目布局定义一个特定的 ViewHolder 类。按照给出的代码进行更深入的了解。
适配器类。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 itemClassList;
// public constructor for this class
public AdapterClass(List 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();
}
}
第 7 步:完成 MainActivity。Java
以下是MainActivity 中要实现的重要任务。 Java文件。
- 将内容视图设置为已实现主要 RecyclerView 的 XML 活动,此处为activity_main.xml 。
- 设置 RecyclerView 的布局。
- 将参数传递给 RecyclerView。
- 设置适配器。
主要活动。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 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);
}
}