RecyclerView
是5.0版本出现的控件,用来替代传统的ListView
,更加强大和灵活。需要添加Design
依赖库,并且使用Theme.AppCompat
主题。
在使用RecyclerView
时候,必须指定一个适配器Adapter
和一个布局管理器LayoutManager
RecyclerView recyclerView = findViewById(R.id.recycler_view);
// 设置布局方式
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(new RecyclerViewAdapter(this));
RecyclerView
的适配器必须继承RecyclerView.Adapter
,并且封装了ViewHolder
的回收复用。
需要实现三个方法
VH onCreateViewHolder(ViewGroup parent, int viewType)
,为每个Item创建一个新的ViewHolder
void onBindViewHolder(VH holder, int position)
,为每个Item赋值int getItemCount()
,返回数量基本适配器实现如下
public final class RecyclerViewAdapter extends RecyclerView.Adapter {
private Context mContext;
private List mContent = new ArrayList<>();
public RecyclerViewAdapter(Context context) {
this.mContext = context;
for (int position = 1; position <= 40; position++) {
mContent.add("This is " + position + " item");
}
}
@NonNull
@Override
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
return new ItemViewHolder(LayoutInflater.from(mContext)
.inflate(R.layout.list_item_text, viewGroup, false));
}
@Override
public void onBindViewHolder(@NonNull ItemViewHolder viewHolder, int position) {
viewHolder.textView.setText(mContent.get(position));
}
@Override
public int getItemCount() {
return mContent.size();
}
class ItemViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
public ItemViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.tv_content);
}
}
}
RecyclerView
提供了三种布局管理器LayoutManager
:
LinerLayoutManager
,以垂直或者水平列表方式展示ItemGridLayoutManager
,以网格方式展示ItemStaggeredGridLayoutManager
,以瀑布流方式展示Item默认的LinerLayoutManager
布局是垂直方向的,调用setOrientation()
方法可以改变方向。
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(RecyclerView.HORIZONTAL);
GridLayoutManager
布局需要指定网格的数量
LinearLayoutManager layoutManager = new GridLayoutManager(this, 4);
StaggeredGridLayoutManager
是瀑布流布局,根据布局的列数来自动适配宽度。
LinearLayoutManager layoutManager = new StaggeredGridLayoutManager(4, RecyclerView.VERTICAL);
RecyclerView
默认没有提供类似addHeaderView()
和addFooterView()
这样的操作,我们只能自己实现。
首先我们需要准备两个ViewHolder
,分别存放列表内容和表头表尾,拥有共同的父类ItemViewHolder
。
class ItemViewHolder extends RecyclerView.ViewHolder {
public ItemViewHolder(@NonNull View itemView) {
super(itemView);
}
// 为每个Item赋值
protected void bindViewHolder(int position) {
}
}
private class ContentViewHolder extends ItemViewHolder {
private TextView textView;
public ContentViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.tv_content);
}
@Override
protected void bindViewHolder(int position) {
textView.setText(mContent.get(position));
}
}
private class HeaderFooterView extends ItemViewHolder {
public HeaderFooterView(@NonNull View itemView) {
super(itemView);
}
}
然后我们在getItemViewType()
里面,根据不同的行号返回不同的ViewType
。将ViewType
分为列表内容和表头表尾,对应不同的ItemViewHolder
。调用bindViewHolder()
方法更新内容。
public final class RecyclerViewAdapter extends RecyclerView.Adapter {
private static final int VIEW_TYPE_HEADER_VIEW = 100;
private static final int VIEW_TYPE_CONTENT_VIEW = 200;
private static final int VIEW_TYPE_FOOTER_VIEW = 300;
private Context mContext;
private List mContent = new ArrayList<>();
private List mHeaderViewList = new ArrayList<>();
private List mFooterViewList = new ArrayList<>();
public RecyclerViewAdapter(Context context) {
this.mContext = context;
for (int position = 1; position <= 20; position++) {
mContent.add("This is " + position + " item");
}
}
@Override
public int getItemViewType(int position) {
if (position < getHeaderViewSize()) {
// 表头的ViewType为1xx
return VIEW_TYPE_HEADER_VIEW + position;
} else if (position >= getHeaderViewSize() + mContent.size()) {
// 表尾的ViewType为3xx
return VIEW_TYPE_FOOTER_VIEW + position - getHeaderViewSize() - mContent.size();
} else {
// 内容的ViewType为200
return VIEW_TYPE_CONTENT_VIEW;
}
}
@NonNull
@Override
public RecyclerViewAdapter.ItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
if (viewType == VIEW_TYPE_CONTENT_VIEW) {
// 返回内容ViewHolder
return new ContentViewHolder(LayoutInflater.from(mContext)
.inflate(R.layout.list_item_text, viewGroup, false));
} else if (viewType < VIEW_TYPE_CONTENT_VIEW) {
// 返回表头ViewHolder
return new HeaderFooterView(mHeaderViewList.get(viewType - VIEW_TYPE_HEADER_VIEW));
} else {
// 返回表尾ViewHolder
return new HeaderFooterView(mFooterViewList.get(viewType - VIEW_TYPE_FOOTER_VIEW));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerViewAdapter.ItemViewHolder viewHolder, int position) {
if (position >= getHeaderViewSize()) {
// 更新Item内容
viewHolder.bindViewHolder(position - getHeaderViewSize());
}
}
@Override
public int getItemCount() {
return getHeaderViewSize() + mContent.size() + getFooterViewSize();
}
public void addHeaderView(View headerView) {
this.mHeaderViewList.add(headerView);
}
public void addFooterView(View footerView) {
this.mFooterViewList.add(footerView);
}
private int getHeaderViewSize() {
return mHeaderViewList.size();
}
private int getFooterViewSize() {
return mFooterViewList.size();
}
}