支持任意Header和Footer的RecyclerView

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);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值