动态添加或删除RecyclerView的头部和底部

一. 效果图

1. 动态添加和删除头部

添加和删除头部

2. 动态添加和删除底部

image

二. 使用

通过调用WrapRecyclerView封装好的添加和删除头部与底部的方法

package com.xinhua.wraprecyclerviewdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.xinhua.wraprecyclerviewdemo.recyclerview.MyRecyclerAdapter;
import com.xinhua.wraprecyclerviewdemo.recyclerview.WrapRecyclerView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private WrapRecyclerView mRecyclerView;
    private Button mBtnAddHeaderTop, mBtnAddHeaderCenter, mBtnAddHeaderBottom;
    private Button mBtnAddFooterTop, mBtnAddFooterCenter, mBtnAddFooterBottom;
    private Button mBtnDelHeaderIndex, mBtnDelHeaderView, mBtnDelHeaderBottom;
    private Button mBtnDelFooterIndex, mBtnDelFooterView, mBtnDelFooterBottom;

    private TextView mHeadertexttView1, mHeadertexttView2, mHeadertexttView3, mHeadertexttView4;
    private TextView mFootertexttView1, mFootertexttView2, mFootertexttView3, mFootertexttView4;


    private List mList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
    }

    private void initView() {
        mRecyclerView = findViewById(R.id.recycler_view);
        mBtnAddHeaderTop = findViewById(R.id.btn_addHeader_top);
        mBtnAddHeaderCenter = findViewById(R.id.btn_addHeader_center);
        mBtnAddHeaderBottom = findViewById(R.id.btn_addHeader_bottom);
        mBtnAddFooterTop = findViewById(R.id.btn_addFooter_top);
        mBtnAddFooterCenter = findViewById(R.id.btn_addFooter_center);
        mBtnAddFooterBottom = findViewById(R.id.btn_addFooter_bottom);

        mBtnDelHeaderIndex = findViewById(R.id.btn_deleteHeader_index);
        mBtnDelHeaderView = findViewById(R.id.btn_deleteHeader_view);
        mBtnDelHeaderBottom = findViewById(R.id.btn_deleteHeader_bottom);
        mBtnDelFooterIndex = findViewById(R.id.btn_deleteFooter_index);
        mBtnDelFooterView = findViewById(R.id.btn_deleteFooter_view);
        mBtnDelFooterBottom = findViewById(R.id.btn_deleteFooter_bottom);

        mBtnAddHeaderTop.setOnClickListener(this);
        mBtnAddHeaderCenter.setOnClickListener(this);
        mBtnAddHeaderBottom.setOnClickListener(this);
        mBtnAddFooterTop.setOnClickListener(this);
        mBtnAddFooterCenter.setOnClickListener(this);
        mBtnAddFooterBottom.setOnClickListener(this);
        mBtnDelHeaderIndex.setOnClickListener(this);
        mBtnDelHeaderView.setOnClickListener(this);
        mBtnDelHeaderBottom.setOnClickListener(this);
        mBtnDelFooterIndex.setOnClickListener(this);
        mBtnDelFooterView.setOnClickListener(this);
        mBtnDelFooterBottom.setOnClickListener(this);

        //新增头部
        mHeadertexttView1 = new TextView(this);
        mHeadertexttView1.setText("新增头部文字1");
        mHeadertexttView2 = new TextView(this);
        mHeadertexttView2.setText("新增头部文字2");
        mHeadertexttView3 = new TextView(this);
        mHeadertexttView3.setText("新增头部文字3");
        mHeadertexttView4 = new TextView(this);
        mHeadertexttView4.setText("新增头部文字4");

        //新增底部
        mFootertexttView1 = new TextView(this);
        mFootertexttView1.setText("新增底部文字1");
        mFootertexttView2 = new TextView(this);
        mFootertexttView2.setText("新增底部文字2");
        mFootertexttView3 = new TextView(this);
        mFootertexttView3.setText("新增底部文字3");
        mFootertexttView4 = new TextView(this);
        mFootertexttView4.setText("新增底部文字4");

        //添加
        mRecyclerView.addHeaderView(mHeadertexttView1);
        mRecyclerView.addHeaderView(mHeadertexttView2);
        mRecyclerView.addHeaderView(mHeadertexttView3);
        mRecyclerView.addHeaderView(mHeadertexttView4);

        mRecyclerView.addFooterView(mFootertexttView1);
        mRecyclerView.addFooterView(mFootertexttView2);
        mRecyclerView.addFooterView(mFootertexttView3);
        mRecyclerView.addFooterView(mFootertexttView4);

    }

    private void initData() {
        mList = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            mList.add("测试数据 -> " + i);
        }
        mRecyclerView.setAdapter(new MyRecyclerAdapter(this, mList));
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_addHeader_top:
                //添加指定index位置的头部,添加布局文件
                mRecyclerView.addHeaderView(R.layout.layout_header_view1, 0);
                break;
            case R.id.btn_addHeader_center:
                //添加指定index位置的头部,添加自定义View
                View headerLayoutView = LayoutInflater.from(this).inflate(R.layout.layout_header_view2, null, false);
                mRecyclerView.addHeaderView(headerLayoutView, 2);
                break;
            case R.id.btn_addHeader_bottom:
                //添加末端头部,添加布局文件
                mRecyclerView.addHeaderView(R.layout.layout_header_view3);
                break;
            case R.id.btn_addFooter_top:
                View footerLayoutView = LayoutInflater.from(this).inflate(R.layout.layout_footer_view1, null, false);
                mRecyclerView.addFooterView(footerLayoutView, 0);
                break;
            case R.id.btn_addFooter_center:
                mRecyclerView.addFooterView(R.layout.layout_footer_view2, 2);
                break;
            case R.id.btn_addFooter_bottom:
                mRecyclerView.addFooterView(R.layout.layout_footer_view3);
                break;
            case R.id.btn_deleteHeader_index:
                //通过index删除指定位置的头部
                mRecyclerView.removeHeaderViewWithIndex(1);
                break;
            case R.id.btn_deleteHeader_view:
                //删除指定view的头部
                mRecyclerView.removeHeaderView(mHeadertexttView3);
                break;
            case R.id.btn_deleteHeader_bottom:
                //删除最后一个头部
                mRecyclerView.removeHeaderViewWithIndex(mRecyclerView.getHeaderItemCount() - 1);
                break;
            case R.id.btn_deleteFooter_index:
                mRecyclerView.removeFooterViewWithIndex(1);
                break;
            case R.id.btn_deleteFooter_view:
                mRecyclerView.removeFooterView(mFootertexttView3);
                break;
            case R.id.btn_deleteFooter_bottom:
                mRecyclerView.removeFooterViewWithIndex(mRecyclerView.getFooterItemCount() - 1);
                break;
        }
    }
}

三.实现

1. 构建RecyclerViewAdapter

根据不同类型返回不同的ViewType来创建不同的ViewHolder,实现区分头部、正常item、底部

public class WrapRecyclerAdapter extends RecyclerView.Adapter {
    private RecyclerView.Adapter mAdapter;
    private SparseArray mHeaderViews;
    private SparseArray mFooterViews;
    private List mHeaderKey;
    private List mFooterKey;


    public WrapRecyclerAdapter(Context context, RecyclerView.Adapter adapter) {
        mAdapter = adapter;
        mHeaderViews = new SparseArray<>();
        mFooterViews = new SparseArray<>();
        mHeaderKey = new ArrayList<>();
        mFooterKey = new ArrayList<>();
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (mHeaderViews.get(viewType) != null) {
            return new ViewHolder(mHeaderViews.get(viewType));
        } else if (mFooterViews.get(viewType) != null) {
            return new ViewHolder(mFooterViews.get(viewType));
        }
        return mAdapter.createViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (isHeaderView(position) || isFooterView(position)) {
            return;
        }
        mAdapter.onBindViewHolder(holder, position - getHeaderItemCount());
    }

    @Override
    public int getItemViewType(int position) {
        if (isHeaderView(position)) {
            return mHeaderKey.get(position);
        } else if (isFooterView(position)) {
            return mFooterKey.get(position - getHeaderItemCount() - getContentItemCount());
        }
        return mAdapter.getItemViewType(position - getHeaderItemCount());
    }
    
    protected void addHeaderView(View view) {
        mHeaderKey.add(view.hashCode());
        mHeaderViews.put(view.hashCode(), view);
    }

    protected void addHeaderView(View view, int index) {
        mHeaderKey.add(index, view.hashCode());
        mHeaderViews.put(view.hashCode(), view);
    }

    protected void addHeaderViewAndNotify(View view) {
        mHeaderKey.add(view.hashCode());
        mHeaderViews.put(view.hashCode(), view);
        notifyItemInserted(getHeaderItemCount() - 1);
    }

    protected void addHeaderViewAndNotify(View view, int index) {
        addHeaderView(view, index);
        notifyItemInserted(index);
    }
    
    ....

2. 构建WrapRecyclerView

构建WrapRecyclerView来实现对头部和底部的动态添加与删除

public class WrapRecyclerView extends RecyclerView {

    private List mHeaderViews;
    private ArrayMap mHeaderViewResMap;
    private List mFooterViews;
    private ArrayMap mFooterViewResMap;
    private WrapRecyclerAdapter mWrapRecycleAdapter;
    private Context mContext;

    public WrapRecyclerView(@NonNull Context context) {
        this(context, null);
    }

    public WrapRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WrapRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        mHeaderViews = new ArrayList<>();
        mFooterViews = new ArrayList<>();
        mHeaderViewResMap = new ArrayMap<>();
        mFooterViewResMap = new ArrayMap<>();
        mContext = context;
    }

    @Override
    public void setAdapter(@Nullable Adapter adapter) {
        if (mWrapRecycleAdapter != null) {
            mWrapRecycleAdapter.getOriginAdapter().unregisterAdapterDataObserver(mAdapterDataObserver);
        }
        if (adapter == null) {
            mWrapRecycleAdapter = null;
        } else {
            adapter.registerAdapterDataObserver(mAdapterDataObserver);
            mWrapRecycleAdapter = new WrapRecyclerAdapter(getContext(), adapter);
            for (int i = 0; i < mHeaderViews.size(); i++) {
                mWrapRecycleAdapter.addHeaderView(mHeaderViews.get(i));
            }
            if (mFooterViews.size() > 0) {
                for (View footerView : mFooterViews) {
                    mWrapRecycleAdapter.addFooterView(footerView);
                }
            }
        }
        super.setAdapter(mWrapRecycleAdapter);
    }
    
    public void addHeaderView(View view) {
        if (view == null) {
            throw new IllegalArgumentException("view is null on addHeaderView(View view)");
        }
        if (!mHeaderViews.contains(view)) {
            mHeaderViews.add(view);
            if (mWrapRecycleAdapter != null) {
                mWrapRecycleAdapter.addHeaderViewAndNotify(view);
            }
        }
    }

    public void addHeaderView(View view, int index) {
        if (index < 0 || index > mHeaderViews.size()) {
            throw new IllegalArgumentException("index out of bounds on addHeaderView(View view, int index)");
        }
        if (!mHeaderViews.contains(view)) {
            mHeaderViews.add(index, view);
            if (mWrapRecycleAdapter != null) {
                mWrapRecycleAdapter.addHeaderViewAndNotify(view, index);
                if (index == 0) {
                    scrollToPosition(index);
                }
            }
        }
    }

    /**
     * recyclerView添加头部view
     *
     * @param layoutId 布局文件
     */
    public void addHeaderView(@LayoutRes int layoutId) {
        if (layoutId == 0) {
            throw new IllegalArgumentException("layoutId is invalid on addHeaderView(int layoutId)");
        }
        if (!mHeaderViewResMap.containsKey(layoutId)) {
            View view = LayoutInflater.from(mContext).inflate(layoutId, null, false);
            if (view == null) {
                throw new IllegalArgumentException("view is null on addHeaderView(View view)");
            }
            mHeaderViewResMap.put(layoutId, view);
            addHeaderView(view);
        }
    }

    public void addHeaderView(@LayoutRes int layoutId, int index) {
        if (layoutId == 0) {
            throw new IllegalArgumentException("layoutId is invalid on addHeaderView(int layoutId)");
        }
        if (!mHeaderViewResMap.containsKey(layoutId)) {
            View view = LayoutInflater.from(mContext).inflate(layoutId, null, false);
            if (view == null) {
                throw new IllegalArgumentException("view is null on addHeaderView(View view)");
            }
            mHeaderViewResMap.put(layoutId, view);
            addHeaderView(view, index);
        }
    }
    
    
    ....
}
  • 项目地址
    https://github.com/summer-0/WrapRecyclerView

你可能感兴趣的:(动态添加或删除RecyclerView的头部和底部)