嵌套的 RecyclerView是RecyclerView 中 RecyclerView的实现。这种布局的一个例子可以在各种应用程序中看到,例如 Play 商店,其中外部(父)RecyclerView 是垂直方向,而内部(子)RecyclerViews 是水平方向。这里开发了类似的布局。
方法:
第一步:添加需要的依赖
在build.gradle(:app)文件中添加以下依赖。 RecyclerView 对应的第一个依赖是必填的,第二个是 CardView 的依赖,因此根据 UI 要求它是可选的。由于这里在子RecyclerView布局中使用了CardView,所以添加了CardView的依赖。
注意:添加依赖项后,单击立即同步。
implementation ‘androidx.recyclerview:recyclerview:1.0.0’
implementation ‘androidx.cardview:cardview:1.0.0’
注意:对于正确版本的依赖项,请在此处检查。
第二步:实现父RecyclerView
父 RecyclerView 在activity_main文件中实现。此处,activity_main 文件仅包含父 RecyclerView,但可以根据需要对其进行自定义。
activity_main
parent_item
child_item
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 ChildItemList;
// Constructor of the class
// to initialize the variables
public ParentItem(
String ParentItemTitle,
List 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 getChildItemList()
{
return ChildItemList;
}
public void setChildItemList(
List childItemList)
{
ChildItemList = childItemList;
}
}
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 {
private List ChildItemList;
// Constructor
ChildItemAdapter(List 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 {
// 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 itemList;
ParentItemAdapter(List 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);
}
}
}
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 ParentItemList()
{
List 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 ChildItemList()
{
List 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;
}
}
第 3 步:为父 RecyclerView 创建项目布局
确定父布局的需求并在 XML 布局文件中添加与它们对应的视图。在这里,布局文件被命名为parent_item 。除了子 RecyclerView 之外,还包括标题的 TextView。
父项
第 4 步:为子 RecyclerView 创建项目布局
子 RecyclerView 的项目布局是在名为child_item的 XML 布局文件中创建的。 Child RecyclerView 包括一个 ImageView 和一个 TextView,两者都包裹在 CardView 中。
下图作为ImageView的资源,因此添加到drawable资源文件夹中。
child_item
第 5 步:为每个 RecyclerView 创建 Item 类。
每个 RecyclerView 都需要一个Java类,其中构造函数初始化项目的参数并声明 getter 和 setter 方法。因此,创建以下Java类:
- ChildItem:该类将为我们希望动态设置的child_item布局的视图实现构造函数、getter 和 setter 方法。
- ParentItem:该类将为我们希望动态设置的parent_item布局的视图实现构造函数、getter 和 setter 方法。
子项
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;
}
}
父项
package com.example.nestedrecyclerview;
import java.util.List;
public class ParentItem {
// Declaration of the variables
private String ParentItemTitle;
private List ChildItemList;
// Constructor of the class
// to initialize the variables
public ParentItem(
String ParentItemTitle,
List 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 getChildItemList()
{
return ChildItemList;
}
public void setChildItemList(
List childItemList)
{
ChildItemList = childItemList;
}
}
第 6 步:为每个 RecyclerViews 创建一个 Adapter 类。
需要一个适配器类来传递要在 RecyclerView 的视图中显示的数据。
ChildItem 和 ParentItem 类都需要一个适配器类。
- ChildAdapter:这是用于保存要在 ChildItem 类的视图中显示的信息的适配器类。
- ParentAdapter:这是用于保存要在 ParentItem 类的视图中显示的信息的适配器类。
在 ParentItemAdapter 类中,创建了该类的一个实例
RecyclerView.RecycledViewPool
该类用于在父 RecyclerView 和子 RecyclerView 之间传递 View。
子项适配器
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 {
private List ChildItemList;
// Constructor
ChildItemAdapter(List 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);
}
}
}
父项适配器
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 {
// 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 itemList;
ParentItemAdapter(List 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);
}
}
}
步骤 7:设置父 RecyclerView 的布局并将参数传递给两个 RecyclerView。要传递给 RecyclerViews 的参数在Java类中给出,该类膨胀父 RecyclerView 的活动(此处为 activity_main)。所以这里的参数将在 MainActivity 文件中传递。
此外,在此处为父 RecyclerView 设置布局。
主要活动
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 ParentItemList()
{
List 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 ChildItemList()
{
List 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;
}
}
输出: