RecyclerView中网格管理器添加FootView,解决FootView单独占一行问题
RecyclerView中添加Footview的情况需要分情况讨论,因为FootView会随着管理器不同出现不同的效果。比如当使用网格管理器的时候,如果网格适配器最后一行占不满一行时,会导致footview没有单独占到一行
使用线性管理器添加FootView,最重要的是两点
1): 需要覆写getItemViewType方法
2):然后根据onCreateViewHolder里面的viewType参数,创建不同的ViewHolder
1、首先定义一个适配器类
由于我们需要实现两个ViewHolder,因此这里继承RecyclerView.Adapter即可
2、定义两个变量表示两种View类型
private static final int TYPE_NORMAL = 1; // 表示加载正常view
private static final int TYPE_FOOT = 2; // 表示加载foot view
3、定义一个变量表示是否添加了FootView
private boolean isFootAdded;
4、覆写getItemCount方法,根据是否添加FootView,返回不同size大小
@Override
public int getItemCount() {
if (!isFootAdded) {
return datas.size();
}
return datas.size() + 1;
}
5、覆写getItemViewType方法,根据是否添加了FootView并且是否滑到最后一个item来返回类型
@Override
public int getItemViewType(int position) {
if (isFootAdded && position == getItemCount() - 1) {
return TYPE_FOOT;
} else {
return TYPE_NORMAL;
}
}
6、覆写onCreateViewHolder,根据viewType来创建返回类型
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_NORMAL) {
View view = LayoutInflater.from(context).inflate(R.layout.activity_recycle_item_main, null, false);
return new MyHolder(view);
} else {
View view = LayoutInflater.from(context).inflate(R.layout.activity_recycle_item_type1, null, false);
return new MyFootView(view);
}
}
7、覆写onBindViewHolder,根据holder来判断view的类型
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof MyFootView) {
return; // FootView不需要绑定
}
MyHolder myHolder = (MyHolder) holder;
myHolder.textView.setText(datas.get(position).getName());
}
8、最后实现两个ViewHolder
static class MyHolder extends RecyclerView.ViewHolder {
private ImageView imageView;
private TextView textView;
public MyHolder(View view) {
super(view);
imageView = view.findViewById(R.id.iv_item);
textView = view.findViewById(R.id.tv_item);
}
}
static class MyFootView extends RecyclerView.ViewHolder {
public MyFootView(View view) {
super(view);
}
}
核心步骤实现完以后 就可以添加FootView
一般是下滑到最后没有数据加载的时候,会将isFootAdded设置为true并且调用notifyItemInserted();方法。现在模拟一下这种情形,当点击第一个item时,添加FootView。
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof MyFootView) {
return;
}
MyHolder myHolder = (MyHolder) holder;
myHolder.textView.setText(datas.get(position).getName());
myHolder.textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (position != 0 && !isFootAdded) {
return; // 点击position为0的位置添加footview
}
isFootAdded = true;
notifyItemInserted(getItemCount() - 1);
}
});
}
具体效果如下:
其中 no more data就是添加的FootView 表示没有更多数据加载了
2、使用网格管理器添加FootView,这里有坑,当数据源是最后一行占不满一行时时,会出现以下效果:
网格布局代码如下:
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
这是因为最后一行数据源没有占满一行,导致FootView接在后面的位置显示出来。因此为了让FootView单独占满一行需要在***Adapter类***新增如下代码:
1、定义一个内部类,继承***GridLayoutManager.SpanSizeLookup***
class GridSpanSizeLookup extends GridLayoutManager.SpanSizeLookup {
@Override
public int getSpanSize(int position) {
if (isFootAdded && position == getItemCount() - 1) {
return gridManager.getSpanCount(); // 如果是FootView直接返回网格布局一行的个数 这里是3
}
return 1; // 正常View的话返回默认1
}
}
2、覆写onAttachedToRecyclerView方法
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
Log.i("wangjiang1", "onAttachedToRecyclerView");
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
gridManager = ((GridLayoutManager) manager);
if (gridSpanSizeLookup == null) {
gridSpanSizeLookup = new GridSpanSizeLookup();
}
gridManager.setSpanSizeLookup(gridSpanSizeLookup);
}
}
这里可以这么理解,默认Item返回1,表示按网格布局正常来显示
如果是FootView,那么返回3,表示FootView需要单独显示一行,感觉理解起来是反的。
大家可以代码试一下。
点击第一个item,最后看效果如下:
FootView单独显示一行。
由于是刚开始写博客,还没摸清楚代码怎么上传github,有时间再补上。