📅  最后修改于: 2023-12-03 15:34:41.664000             🧑  作者: Mango
RecyclerView 是 Android 开发中常见的列表控件,虽然在大部分情况下都是只展示一个类型的列表数据,但有时也需要展示多种不同类型的列表数据。本文将介绍如何在 RecyclerView 中使用多种视图类型。
使用多种视图类型需要以下步骤:
在 RecyclerView 中,每个视图的展示都需要一个对应的 ViewHolder。定义 ViewHolder 主要需要继承自 RecyclerView.ViewHolder,然后定义对应视图中的控件。
定义两个 ViewHolder 如下:
public class ItemOneViewHolder extends RecyclerView.ViewHolder {
public TextView title, content;
public ItemOneViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title_one);
content = itemView.findViewById(R.id.content_one);
}
}
public class ItemTwoViewHolder extends RecyclerView.ViewHolder {
public TextView title, description;
public ItemTwoViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title_two);
description = itemView.findViewById(R.id.description_two);
}
}
在 Adapter 中使用 getItemViewType 方法返回不同数据类型对应的视图类型。并在 onCreateViewHolder 中创建对应的 ViewHolder。
public class MultiViewTypeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Item> items;
private static final int TYPE_ONE = 0;
private static final int TYPE_TWO = 1;
public MultiViewTypeAdapter(List<Item> items) {
this.items = items;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_ONE:
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_one, parent, false);
return new ItemOneViewHolder(view);
case TYPE_TWO:
View viewTwo = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_two, parent, false);
return new ItemTwoViewHolder(viewTwo);
default:
throw new IllegalArgumentException("Unsupported viewType: " + viewType);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Item item = items.get(position);
switch (getItemViewType(position)) {
case TYPE_ONE:
ItemOneViewHolder viewHolder1 = (ItemOneViewHolder) holder;
viewHolder1.title.setText(item.getTitle());
viewHolder1.content.setText(item.getContent());
break;
case TYPE_TWO:
ItemTwoViewHolder viewHolder2 = (ItemTwoViewHolder) holder;
viewHolder2.title.setText(item.getTitle());
viewHolder2.description.setText(item.getDescription());
break;
default:
throw new IllegalArgumentException("Unsupported viewType: " + getItemViewType(position));
}
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public int getItemViewType(int position) {
Item item = items.get(position);
if (item.getType() == Item.TYPE_ONE) {
return TYPE_ONE;
} else if (item.getType() == Item.TYPE_TWO) {
return TYPE_TWO;
} else {
throw new IllegalArgumentException("Unsupported item type: " + item.getType());
}
}
}
在 ViewHolder 中绑定数据,这里可以使用多态。
public abstract class BaseViewHolder extends RecyclerView.ViewHolder {
public BaseViewHolder(@NonNull View itemView) {
super(itemView);
}
public abstract void bindData(Item item);
}
public class ItemOneViewHolder extends BaseViewHolder {
private TextView title, content;
public ItemOneViewHolder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title_one);
content = itemView.findViewById(R.id.content_one);
}
@Override
public void bindData(Item item) {
title.setText(item.getTitle());
content.setText(item.getContent());
}
}
public class ItemTwoViewHolder extends BaseViewHolder {
private TextView title, description;
public ItemTwoViewHolder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title_two);
description = itemView.findViewById(R.id.description_two);
}
@Override
public void bindData(Item item) {
title.setText(item.getTitle());
description.setText(item.getDescription());
}
}
然后在 Adapter 中使用 BaseViewHolder 即可。
public class MultiViewTypeAdapter extends RecyclerView.Adapter<BaseViewHolder> {
private List<Item> items;
private static final int TYPE_ONE = 0;
private static final int TYPE_TWO = 1;
public MultiViewTypeAdapter(List<Item> items) {
this.items = items;
}
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_ONE:
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_one, parent, false);
return new ItemOneViewHolder(view);
case TYPE_TWO:
View viewTwo = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_two, parent, false);
return new ItemTwoViewHolder(viewTwo);
default:
throw new IllegalArgumentException("Unsupported viewType: " + viewType);
}
}
@Override
public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
Item item = items.get(position);
holder.bindData(item);
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public int getItemViewType(int position) {
Item item = items.get(position);
if (item.getType() == Item.TYPE_ONE) {
return TYPE_ONE;
} else if (item.getType() == Item.TYPE_TWO) {
return TYPE_TWO;
} else {
throw new IllegalArgumentException("Unsupported item type: " + item.getType());
}
}
}
使用多种视图类型的 RecyclerView 示例代码:https://github.com/fanxuankai/MultiViewTypeDemo
使用 RecyclerView 显示多种视图类型需要实现多个 ViewHolder,使用 getItemViewType 方法返回不同数据类型对应的视图类型,使用 BaseViewHolder 让代码更简洁易懂。