📌  相关文章
📜  RecyclerView 在 Android 中的多种视图类型与示例(1)

📅  最后修改于: 2023-12-03 15:34:41.664000             🧑  作者: Mango

RecyclerView 在 Android 中的多种视图类型与示例

简介

RecyclerView 是 Android 开发中常见的列表控件,虽然在大部分情况下都是只展示一个类型的列表数据,但有时也需要展示多种不同类型的列表数据。本文将介绍如何在 RecyclerView 中使用多种视图类型。

多种视图类型

使用多种视图类型需要以下步骤:

  1. 为 RecyclerView 定义多个不同类型的 ViewHolder。
  2. 在 Adapter 中根据不同类型的数据返回对应的 ViewHolder。
  3. 在 ViewHolder 中绑定不同类型的数据。
定义多个 ViewHolder

在 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);
    }
}
返回对应的 ViewHolder

在 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 让代码更简洁易懂。