border="0" width="840" height="86" src="//music.163.com/outchain/player?type=2&id=416892296&auto=1&height=66">请注明出处:http://blog.csdn.net/qq_23179075/article/details/78984197
RecyclerView中添加通用FooterView和HeaderView
都知道 ListView提供了 addFooterView()
和 addHeaderView()
两个方法来给列表添加 底部 和 头部 的布局,但是现在很多应用中都放弃了 ListView 这个控件从而选择 RecyclerView 这个强大的控件,RecyclerView 的强大主要在于它的高度灵活性。存在于 ListView 中的一些常用的功能,在 RecyclerView 中都需要程序员自己实现。比如:item 的点击事件、item 的分割线等等。
RecyclerView 中实现 FooterView 和 HeaderView 方式有多种,这里仅代表个人实现方法。
本文主要讲在 RecyclerView 中添加 FooterView , 因为 HeaderView 实现方式都大同小异,就不用赘述了。
先看效果
上图的 点击刷新 就是本文所添加的 FooterView,底部布局很简单,当然底部什么样子都是根据需求来定。
下面上图的实现代码讲解。本文主要是通过自定义 Adapter 的方式来实现的。主要的核心是,实现父类 RecyclerView.Adapter<> 的 getItemViewType(int position)
。通过这个方法我们可以为每个 item 设置一个 Type,
@Override
public int getItemViewType(int position) {
//将list的最后一个item的Type设置为footer,其余的都设置成正常显示,
//如果有HeaderView,可以将第一个设置为 header
if (position == getItemCount() - 1) {
return TYPE_FOOTER;
}
return TYPE_NORMAL;
}
在 onCreateViewHolder(ViewGroup parent, int viewType)
的是实现方法中通过这个 Type ,来判断当前item来创建相应的 ViewHolder。
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//通过判断item的类型,创建对应的ViewHolder
if (viewType == TYPE_FOOTER) {
//加载footer的ViewHolder
return footerViewHolder(parent);
}
//加载item的ViewHolder
return itemViewHolder(parent);
}
当然在 onBindViewHolder(RecyclerView.ViewHolder holder, int position)
中也需要通过 itme 的 Type 来绑定对应的 Holoder 。
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
//通过判断item的类型,绑定不同的ViewHolder
if (viewType == TYPE_NORMAL) {
onBindItemViewHolder((IVH) holder,position);
}else {
onBindFooterViewHolder((FVH) holder,position);
}
}
本文在这里是实现了一个抽象的 BaseFooterAdapter 类,如果需求中有 FooterView ,就可以继承该类来实现,下面是这个类的所有代码:
/**
* @author zhengliang
* @data 2018/1/5.
* 这里通过范型的方式传入 Item和Footer的ViewHolder的实现类
*/
public abstract class BaseFooterAdapter<IVH extends RecyclerView.ViewHolder,FVH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
/**
* 说明是带有Footer的
*/
private static final int TYPE_FOOTER = 1;
/**
* 正常的item
*/
private static final int TYPE_NORMAL = 2;
/**
* item点击事件
*/
protected OnItemViewClickListener itemListener;
/**
* footer中的点击事件
*/
protected OnItemViewClickListener footerListener;
@Override
public int getItemViewType(int position) {
//将list的最后一个item的Type设置为footer;
if (position == getItemCount() - 1) {
return TYPE_FOOTER;
}
return TYPE_NORMAL;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//通过判断item的类型,创建对应的ViewHolder
if (viewType == TYPE_FOOTER) {
//加载footer
return footerViewHolder(parent);
}
return itemViewHolder(parent);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
//通过判断item的类型,绑定不同的ViewHolder
if (viewType == TYPE_NORMAL) {
onBindItemViewHolder((IVH) holder,position);
}else {
onBindFooterViewHolder((FVH) holder,position);
}
}
@Override
public int getItemCount() {
//因为最后一个item是Footer,所以要+1
return getItemCountSize()+1;
}
/**
* 子类实现列表的大小
* @return
*/
public abstract int getItemCountSize();
/**
* item布局实现
* @param parent
* @return
*/
public abstract IVH itemViewHolder(ViewGroup parent);
/**
* 底部布局实现
* @param parent
* @return
*/
public abstract FVH footerViewHolder(ViewGroup parent);
/**
* 绑定item
* @param holder
* @param position
*/
public abstract void onBindItemViewHolder(IVH holder, int position);
/**
* 绑定footer
* @param holder
* @param position
*/
public abstract void onBindFooterViewHolder(FVH holder, int position);
public void setItemViewClickListener(OnItemViewClickListener listener) {
this.itemListener = listener;
}
public void setFooterListener(OnItemViewClickListener footerListener) {
this.footerListener = footerListener;
}
/**
* date 2017/8/9
* @author zhengliang
* 自定义点击事件
*/
public interface OnItemViewClickListener {
/**
* 单击事件
*
* @param view 控件
* @param position 位置
*/
void onClick(View view, int position);
}
}
代码就不逐句讲解,相信注释都能明白。如果需要 HeaderView 就在泛型中加 HeaderViwe 的 Holder ,然后对应处理下 HeaderView 的 Type 就行了,都是和 HeaderView 一样一样的。
接下来看看如果使用
/**
* @author zhengliang
*/
public class ItemTaskListAdapter extends BaseFooterAdapter<ItemTaskListAdapter.MyItemViewHolder,ItemTaskListAdapter.MyFooterViewHolder> {
private Context context;
private List<TaskListResp.ContentBean> taskList;
public ItemTaskListAdapter(Context context) {
this.context = context;
this.taskList = new ArrayList<>();
}
public void addAll(List<TaskListResp.ContentBean> taskList) {
this.taskList = taskList;
this.notifyDataSetChanged();
}
@Override
public int getItemCountSize() {
return taskList.size();
}
@Override
public MyItemViewHolder itemViewHolder(ViewGroup parent) {
return new MyItemViewHolder(LayoutInflater.from(context).inflate(R.layout.item_task, parent, false));
}
@Override
public MyFooterViewHolder footerViewHolder(ViewGroup parent) {
return new MyFooterViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_footer_refresh, parent, false));
}
@SuppressLint("SetTextI18n")
@Override
public void onBindItemViewHolder(MyItemViewHolder holder, int position) {
TaskListResp.ContentBean task = taskList.get(position);
holder.tvTitle.setText(task.getTitle());
holder.tvDescription.setText(task.getDescription());
holder.tvTime.setText(DateUtils.stampFormatTime(task.getEntryDt(), "yyyy-MM-dd HH:mm"));
if (super.itemListener != null) {
holder.root.setOnClickListener(v -> super.itemListener.onClick(v, position));
}
}
@Override
public void onBindFooterViewHolder(MyFooterViewHolder holder, int position) {
if (super.footerListener != null) {
holder.rvFooter.setOnClickListener(v -> super.footerListener.onClick(v, position));
}
}
class MyItemViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.root)
RelativeLayout root;
@BindView(R.id.iv_img)
ImageView ivImg;
@BindView(R.id.tv_title)
TextView tvTitle;
@BindView(R.id.tv_description)
TextView tvDescription;
@BindView(R.id.tv_time)
TextView tvTime;
@BindView(R.id.iv_enter)
ImageView ivEnter;
MyItemViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
class MyFooterViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.rv_footer)
RelativeLayout rvFooter;
MyFooterViewHolder(View footerView) {
super(footerView);
ButterKnife.bind(this, footerView);
}
}
}
只要对应实现 BaserFooterAdapter 的抽象方法就行了,跟之前使用 Adapter 一样。