RecyclerView中网格管理器添加FootView,解决FootView单独占一行问题
RecyclerView中添加Footview的情况需要分情况讨论,因为FootView会随着管理器不同出现不同的效果。比如当使用网格管理器的时候,如果网格适配器最后一行占不满一行时,会导致footview没有单独占到一行

使用线性管理器添加FootView,最重要的是两点
1): 需要覆写getItemViewType方法
2):然后根据onCreateViewHolder里面的viewType参数,创建不同的ViewHolder

1、首先定义一个适配器类

android recycleview显示中间 recyclerview只显示一行_加载


由于我们需要实现两个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);
        }
    });
}

具体效果如下:

android recycleview显示中间 recyclerview只显示一行_覆写_02

其中 no more data就是添加的FootView 表示没有更多数据加载了

2、使用网格管理器添加FootView,这里有坑,当数据源是最后一行占不满一行时时,会出现以下效果:

android recycleview显示中间 recyclerview只显示一行_加载_03

网格布局代码如下:

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,最后看效果如下:

android recycleview显示中间 recyclerview只显示一行_ide_04

FootView单独显示一行。

由于是刚开始写博客,还没摸清楚代码怎么上传github,有时间再补上。