声明:原创作品,转载请注明出处:https://www.jianshu.com/p/7d30ba789a46
我在上一篇文章《RecyclerView使用指南(一)—— 基本使用》中讲解了RecyclerView的最基本用法。
这一篇,我来讲解一下多种条目布局应该如何显示。(如果没看过上一篇文章的小朋友,建议去看一下短小的上一篇文章。。。)
没图说个**:
- 核心思路:
- 针对不同的条目布局,我们创建不同的ViewHolder。
- Adapter需要知道在什么情况下使用什么样的布局。
Adapter中,我们可以通过重写getItemViewType(int position)方法,根据数据源,返回不同的viewType,Adapter在onCreateViewHolder和onBindViewHolder方法中使用这个值来创建ViewHolder和绑定相应的数据。
一、数据源为同种类型
总上所述,我们可以写一个简单的示例代码,它的数据源都是Data类型。如下:
package com.liuym.myapplication;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
public class RvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
//条目类型
public static final int TYPE_0 = 0;
public static final int TYPE_1 = 1;
//数据源
private List<Data> mList;
public RvAdapter(List<Data> list) {
mList = list;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
View item;
RecyclerView.ViewHolder holder = null;
if (viewType == TYPE_0) {
item = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_rv_type1, viewGroup, false);
holder = new Type0ViewHolder(item);
}
if (viewType == TYPE_1) {
item = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_rv_type2, viewGroup, false);
holder = new Type1ViewHolder(item);
}
return holder;
}
/**
* 根据数据源的某一项,返回相应的布局类别
*
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
return mList.get(position).getType();
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
int type = getItemViewType(i);
Data data = mList.get(i);
if (type == TYPE_0) {
Type0ViewHolder holder = (Type0ViewHolder) viewHolder;
holder.iv.setImageResource(R.drawable.ic_launcher_background);
holder.tv.setText(data.getText());
}
if (type == TYPE_1) {
Type1ViewHolder holder = (Type1ViewHolder) viewHolder;
holder.iv.setImageResource(R.drawable.ic_launcher_background);
holder.tv.setText(data.getText());
}
}
@Override
public int getItemCount() {
return mList == null ? 0 : mList.size();
}
class Type0ViewHolder extends RecyclerView.ViewHolder {
ImageView iv;
TextView tv;
public Type0ViewHolder(@NonNull View itemView) {
super(itemView);
iv = itemView.findViewById(R.id.iv);
tv = itemView.findViewById(R.id.tv);
}
}
class Type1ViewHolder extends RecyclerView.ViewHolder {
ImageView iv;
TextView tv;
public Type1ViewHolder(@NonNull View itemView) {
super(itemView);
iv = itemView.findViewById(R.id.iv);
tv = itemView.findViewById(R.id.tv);
}
}
}
二、数据源为不同类型
那么,如果我们要显示不同种类型的怎么办呢?比如这个列表既包含铅笔,又包含橡皮,怎么办?
这里,我们的数据源要包含两个类:Pencil类和Eraser类,为了将它们放到同一个列表中,我们可以让它们实现同一个接口,讲到这里,是不是有思路了呢?
好,我们来实现这个功能!
- 创建一个接口:
package com.liuym.myapplication;
public interface IMultiType {
/**
* 返回条目类型
*
* @return
*/
int getItemType();
}
- 创建Pencil类实现IMultiType接口(Eraser类和Pencil类基本一致,只是返回的itemType不同):
package com.liuym.myapplication;
public class Pencil implements IMultiType {
private String msg;
public Pencil(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public int getItemType() {
return RvAdapter.TYPE_PENCIL;
}
}
- 修改Adapter的数据源,将IMultiType的子类放入到数据源中,重写getItemViewType(int position)方法,完整代码如下:
package com.liuym.myapplication;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
public class RvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
//条目类型
public static final int TYPE_PENCIL = 0;
public static final int TYPE_ERASER = 1;
//数据源
private List<IMultiType> mList;
public RvAdapter(List<IMultiType> list) {
mList = list;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
View item;
RecyclerView.ViewHolder holder = null;
if (viewType == TYPE_PENCIL) {
item = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_rv_type1, viewGroup, false);
holder = new PencilViewHolder(item);
}
if (viewType == TYPE_ERASER) {
item = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_rv_type2, viewGroup, false);
holder = new EraserViewHolder(item);
}
return holder;
}
/**
* 根据数据源的某一项,返回相应的布局类别
*
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
return mList.get(position).getItemType();
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
int type = getItemViewType(i);
if (type == TYPE_PENCIL) {
Pencil pencil = (Pencil) mList.get(i);
PencilViewHolder holder = (PencilViewHolder) viewHolder;
holder.iv.setImageResource(R.drawable.ic_launcher_background);
holder.tv.setText(pencil.getMsg());
}
if (type == TYPE_ERASER) {
Eraser eraser = (Eraser) mList.get(i);
EraserViewHolder holder = (EraserViewHolder) viewHolder;
holder.iv.setImageResource(R.drawable.ic_launcher_background);
holder.tv.setText(eraser.getMsg());
}
}
@Override
public int getItemCount() {
return mList == null ? 0 : mList.size();
}
class PencilViewHolder extends RecyclerView.ViewHolder {
ImageView iv;
TextView tv;
public PencilViewHolder(@NonNull View itemView) {
super(itemView);
iv = itemView.findViewById(R.id.iv);
tv = itemView.findViewById(R.id.tv);
}
}
class EraserViewHolder extends RecyclerView.ViewHolder {
ImageView iv;
TextView tv;
public EraserViewHolder(@NonNull View itemView) {
super(itemView);
iv = itemView.findViewById(R.id.iv);
tv = itemView.findViewById(R.id.tv);
}
}
}
- 设置数据源给Adapter,并将Adapter设置给RecyclerView
private void initRv() {
List<IMultiType> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
if (i % 2 == 0) {
String msg = String.format("eraser: %1s", i);
list.add(new Eraser(msg));
} else {
String msg = String.format("pencil: %1s", i);
list.add(new Pencil(msg));
}
}
RecyclerView recyclerView = findViewById(R.id.rv);
RvAdapter adapter = new RvAdapter(list);
recyclerView.setAdapter(adapter);
}
总结
这一篇,我讲解了如何在RecyclerView中使用不同的布局,下一篇,我会讲解如何给RecyclerView添加分割线以及给Item设置点击事件。
系列文章
《RecyclerView使用指南(一)—— 基本使用》
《RecyclerView使用指南(二)—— 多种ItemLayout》
《RecyclerView使用指南(三)—— 添加分割线和点击事件》
《RecyclerView使用指南(四)—— 使用ItemDecoration》
《RecyclerView使用指南(五)—— 实现吸顶效果》