22-09-11更新,重写里面了HeaderOrFooterRecyclerAdapter,完美实现任意Header和任意Footer,并且支持Header和Footer移除
第一部分:WrapRecyclerView
直接当作RecyclerView使用,使用默认的RecyclerView.Adapter,它多了添加Header和添加footer的方法
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
/**
* description: 支持添加底部和头部的 RecyclerView
* author: Darren on 2017/9/27 10:07
* email: 240336124@qq.com
* version: 1.0
*/
public class WrapRecyclerView extends RecyclerView {
// 支持添加头部和底部的 RecyclerView.Adapter
public HeaderOrFooterRecyclerAdapter mWrapAdapter;
public WrapRecyclerView(Context context) {
super(context);
}
public WrapRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public WrapRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setAdapter(Adapter adapter) {
// 这里做一个替换
mWrapAdapter = new HeaderOrFooterRecyclerAdapter(adapter);
super.setAdapter(mWrapAdapter);
}
/**
* 添加头部View
*/
public void addHeaderView(View view){
if(mWrapAdapter != null){
mWrapAdapter.addHeaderView(view);
}
}
/**
* 添加底部View
*/
public void addFooterView(View view){
if(mWrapAdapter != null){
mWrapAdapter.addFooterView(view);
}
}
/**
* 移除头部View
*/
public void removeHeaderView(View view){
if(mWrapAdapter != null){
mWrapAdapter.removeHeaderView(view);
}
}
/**
* 移除底部View
*/
public void removeFooterView(View view){
if(mWrapAdapter != null){
mWrapAdapter.removeFooterView(view);
}
}
//判断当前item是否是HeadView
public boolean isHeaderView(int position) {
if(mWrapAdapter != null){
return position < mWrapAdapter.getHeadersCount();
}
return false;
}
/**
* 是否为header
* */
public boolean isHeaderView(View view){
if(mWrapAdapter != null){
return mWrapAdapter.isHeaderView(view);
}
return false;
}
/**
* 是否为footer
* */
public boolean isFooterView(View view){
if(mWrapAdapter != null){
return mWrapAdapter.isFooterView(view);
}
return false;
}
//判断当前item是否是FootView
public boolean isFooterView(int position) {
if(mWrapAdapter != null){
return position >= (mWrapAdapter.getHeadersCount() + mWrapAdapter.mRealAdapter.getItemCount());
}
return false;
}
//获取顶部栏的数量
public int getHeaderCount(){
if(mWrapAdapter != null){
return mWrapAdapter.getHeadersCount();
}
return 0;
}
//获取底部栏的数量
public int getFooterCount(){
if(mWrapAdapter != null){
return mWrapAdapter.getFooterCount();
}
return 0;
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataSetChanged(){
if(mWrapAdapter != null)mWrapAdapter.notifyDataSetChanged();
}
public void notifyHeaderOrFooterItemChange(View view){
if(mWrapAdapter != null)mWrapAdapter.notifyHeaderOrFooterItemChange(view);
}
}
第二部分:HeaderOrFooterRecyclerAdapter
此类只需要添加,不需要手动使用,在WrapRecyclerView中会被调用
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
/**
* description: 可以添加头部底部的 AddTopAndBottomViewRecyclerAdapter
* author: Darren on 2017/9/25 09:54
* email: 240336124@qq.com
* version: 1.0
*
* 作者:Pine
* 时间:2022/09/03
* 日志:原作者代码有问题,因为type设置有问题导致footer的holder被回收作为原adapter的holder,然后类型转换失败闪退
*/
public class HeaderOrFooterRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
// 包装 adapter 是原来的 RecyclerView.Adapter 是并不支持添加头部和底部的
public RecyclerView.Adapter mRealAdapter;
private final ArrayList<View> mHeaderViews; // 头部
private final ArrayList<View> mFooterViews; // 底部
public HeaderOrFooterRecyclerAdapter(RecyclerView.Adapter adapter) {
mRealAdapter = adapter;
mHeaderViews = new ArrayList<>();
mFooterViews = new ArrayList<>();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//为每个Header构建一个Holder
if(viewType==99999){
LinearLayout linearLayout=new LinearLayout(parent.getContext());
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new HeaderOrFooterHolder(linearLayout);
}
//让原始adapter构建对应的Holder
else{
return mRealAdapter.onCreateViewHolder(parent, mRealAdapter.getItemViewType(viewType));
}
}
/**
* 构建一个holder
* 但holder的view被线性布局包裹
* 方便view复用
* */
public static class HeaderOrFooterHolder extends RecyclerView.ViewHolder{
@NonNull
private final LinearLayout linearLayout;
public HeaderOrFooterHolder(@NonNull LinearLayout linearLayout) {
super(linearLayout);
this.linearLayout = linearLayout;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//绑定Header或者Footer
if(holder instanceof HeaderOrFooterHolder){
//拿到对应的Header或footer
View headerOrFooterView;
if(position<getHeadersCount()){
headerOrFooterView=mHeaderViews.get(position);
}else{
headerOrFooterView=mFooterViews.get(position-(getHeadersCount()+mRealAdapter.getItemCount()));
}
//从父类布局中移除
ViewParent viewParent=headerOrFooterView.getParent();
if(viewParent !=null){
((ViewGroup)viewParent).removeView(headerOrFooterView);
}
//添加进holder
HeaderOrFooterHolder headerOrFooterHolder=(HeaderOrFooterHolder)holder;
headerOrFooterHolder.linearLayout.removeAllViews();
headerOrFooterHolder.linearLayout.addView(headerOrFooterView);
}
//原Adapter绑定数据,减去header才是原始值
else{
mRealAdapter.onBindViewHolder(holder, position-getHeadersCount());
}
}
/**
* 返回View类型
* */
@Override
public int getItemViewType(int position) {
//返回header类型
if(position<getHeadersCount()){
return 99999;
}
//返回原始类型
int removeHeaderPosition=position-getHeadersCount();
if(removeHeaderPosition<mRealAdapter.getItemCount()){
return mRealAdapter.getItemViewType(removeHeaderPosition);
}
//返回footer类型
return 99999;
}
//获取顶部栏的数量
public int getHeadersCount() {
return mHeaderViews.size();
}
//获取底部栏的数量
public int getFooterCount(){return mFooterViews.size();}
/**
* 添加头部View
*/
public void addHeaderView(View view) {
if (!mHeaderViews.contains(view)) {
//添加进recyclerView
mHeaderViews.add(view);
notifyItemInserted(mHeaderViews.size()-1);
}
}
/**
* 添加底部View
*/
public void addFooterView(View view) {
if (!mFooterViews.contains(view)) {
//添加进recyclerView
mFooterViews.add(view);
notifyItemInserted(mHeaderViews.size()+mRealAdapter.getItemCount()+mFooterViews.size()-1);
}
}
/**
* 移除头部View
*/
public void removeHeaderView(View view) {
if (mHeaderViews.contains(view)) {
int i = mHeaderViews.indexOf(view);
mHeaderViews.remove(view);
notifyItemRemoved(i);
//从Holder父类中移除
ViewParent viewParent=view.getParent();
if(viewParent !=null){
((ViewGroup)viewParent).removeView(view);
}
}
}
/**
* 移除底部View
*/
public void removeFooterView(View view) {
if (mFooterViews.contains(view)) {
int i = mFooterViews.indexOf(view);
mFooterViews.remove(view);
notifyItemRemoved(mHeaderViews.size()+mRealAdapter.getItemCount()+i);
//从Holder父类中移除
ViewParent viewParent=view.getParent();
if(viewParent !=null){
((ViewGroup)viewParent).removeView(view);
}
}
}
public void notifyHeaderOrFooterItemChange(View view){
if (mFooterViews.contains(view)) {
notifyItemChanged(mFooterViews.indexOf(view));
}
else if(mHeaderViews.contains(view)){
notifyItemChanged(mHeaderViews.indexOf(view));
}
}
@Override
public int getItemCount() {
return mRealAdapter.getItemCount() + mHeaderViews.size() + mFooterViews.size();
}
/**
* 是否为header
* */
public boolean isHeaderView(View view){
return mHeaderViews.contains(view);
}
/**
* 是否为footer
* */
public boolean isFooterView(View view){
return mFooterViews.contains(view);
}
}