RecyclerView正确添加Header

如何为RecyclerView添加Header

在Android开发中,经常会遇到列表页面,在使用Listview的时候,有专门的方法去添加header,但使用recyclerView的时候,无论是recyclerView还是LayoutManager都没有专门的方法去添加header,那如何给recyclerView添加header呢,网上有很多,最普遍的方法就是通过控制Adapter的itemType来设置的,思路就是根据不同的itemType去加载不同的布局。

public abstract class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.RecycleHolder> {

private Context mContext;
public List<T> mBodyDatas;
private int mBodyLayoutId, mHeaderLayoutId;
private LayoutInflater mInflater;

//item类型
public static final int ITEM_TYPE_HEADER = 0;//头
public static final int ITEM_TYPE_CONTENT = 1;//主体

private int mHeaderCount;//头部View个数
public OnItemClickListener onItemClickListener;//item监听

public RecyclerAdapter(Context mContext, List<T> mBodyDatas, int mBodyLayoutId) {
    this(mContext, mBodyDatas, mBodyLayoutId, 0);
}

public RecyclerAdapter(Context mContext, List<T> mBodyDatas, int mBodyLayoutId, int mHeaderLayoutId) {
    this.mContext = mContext;
    this.mBodyDatas = mBodyDatas;
    this.mBodyLayoutId = mBodyLayoutId;
    this.mHeaderLayoutId = mHeaderLayoutId;
    mInflater = LayoutInflater.from(mContext);
    //判断是否有头
    if (mHeaderLayoutId == 0) {
        mHeaderCount = 0;
    } else {
        mHeaderCount = 1;
    }
}

@NonNull
@Override
public RecycleHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    if (viewType == ITEM_TYPE_HEADER) {
        return new RecycleHolder(mInflater.inflate(mHeaderLayoutId, parent, false));
    } else if (viewType == ITEM_TYPE_CONTENT) {
        return new RecycleHolder(mInflater.inflate(mBodyLayoutId, parent, false));
    }
    return null;
}

@Override
public void onBindViewHolder(@NonNull final RecyclerAdapter.RecycleHolder holder, int position) {
    //根据item的类型实现与不同数据源进行衔接
    if (isHeaderView(position)) {
        convertHeader(holder, null, position);
    } else {
        convertBody(holder, mBodyDatas.get(position - mHeaderCount), position);
        if (onItemClickListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //注意,这里的position不要用上面参数中的position,会出现位置错乱\
                    onItemClickListener.OnItemClickListener(holder.itemView, holder.getLayoutPosition() - mHeaderCount);
                }
            });
        }
    }

}

@Override
public int getItemCount() {
    return mBodyDatas.size() + mHeaderCount;
}

/**
 * 返回主体item的个数
 *
 * @return
 */
public int getContentItemCount() {
    return mBodyDatas.size();
}

@Override
public int getItemViewType(int position) {
    if (mHeaderCount != 0 && position < mHeaderCount) {
        return ITEM_TYPE_HEADER;
    }
    return ITEM_TYPE_CONTENT;
}

/**
 * 判断当前item是否是HeadView
 *
 * @param position
 * @return
 */
public boolean isHeaderView(int position) {
    return mHeaderCount != 0 && position < mHeaderCount;
}


/**
 * 将主体数据源添加到主体上-----必须要重写
 *
 * @param holder
 * @param data
 * @param position
 */
public abstract void convertBody(RecycleHolder holder, T data, int position);


/**
 * 将头部数据源添加到头部-----recyclerView添加头部时重写
 *
 * @param holder
 * @param data
 * @param position
 */
public void convertHeader(RecycleHolder holder, T data, int position) {

}

/**
 * 为recycler View设置item的点击事件
 *
 * @param onItemClickListener
 */
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
    this.onItemClickListener = onItemClickListener;
}

//点击事件监听接口
public interface OnItemClickListener {
    void OnItemClickListener(View view, int position);
}

public List<T> getmBodyDatas() {
    return mBodyDatas;
}

public class RecycleHolder extends RecyclerView.ViewHolder {
    /**
     * 用于存储当前item当中的View
     */
    private SparseArray<View> mViews;

    public RecycleHolder(View itemView) {
        super(itemView);
        mViews = new SparseArray<View>();
    }

    public <T extends View> T findView(int ViewId) {
        View view = mViews.get(ViewId);
        //集合中没有,则从item当中获取,并存入集合当中
        if (view == null) {
            view = itemView.findViewById(ViewId);
            mViews.put(ViewId, view);
        }
        return (T) view;
    }

    public RecycleHolder setText(int viewId, String text) {
        TextView tv = findView(viewId);
        tv.setText(text);
        return this;
    }

    public RecycleHolder setText(int viewId, int text) {
        TextView tv = findView(viewId);
        tv.setText(text);
        return this;
    }

    public RecycleHolder setImageResource(int viewId, int ImageId) {
        ImageView image = findView(viewId);
        image.setImageResource(ImageId);
        return this;
    }

    public RecycleHolder setImageBitmap(int viewId, Bitmap bitmap) {
        ImageView imageView = findView(viewId);
        imageView.setImageBitmap(bitmap);
        return this;
    }
}

public void addDatas(List<T> lists) {
    if (mBodyDatas == null) {
        mBodyDatas = new ArrayList<>();
    }
    mBodyDatas.clear();
    if (null == lists) {
        return;
    }
    mBodyDatas.addAll(lists);
    notifyDataSetChanged();
}
public void appendDatas(List<T> lists) {
    if (null == lists) {
        return;
    }
    if (mBodyDatas == null) {
        mBodyDatas = new ArrayList<>();
    }
    mBodyDatas.addAll(lists);
    notifyDataSetChanged();
}

}

这里重写了getItemViewType方法,并根据位置来返回不同的type,这个type是我们预先商定好的常量,接在onCreateViewHolder方法中来判断itemType,如果是header,则加载设置的header布局,否则正常加载item布局。

为GridLayoutManager添加header

最近公司再做一个项目,样式如下图
在这里插入图片描述
GridLayoutManager mgr = new GridLayoutManager(this, 2);
在这里插入图片描述
然后出现这么个玩意 ,和我们需求不一样啊,这时候我们就要去看源码和查资料了,发现有这么一个方法
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return getItemViewType(position) == ITEM_TYPE_HEADER
? gridManager.getSpanCount() : 1;
}
});
大致意思是当前位置是header时,占用你前面设置的单元格,其它的占用一个单元格,为了使用方便,在RecyclerAdapter中进行封装
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if(manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return getItemViewType(position) == ITEM_TYPE_HEADER
? gridManager.getSpanCount() : 1;
}
});
}
}
这时候,我们在跑一下我们的项目,就能实现我们的效果了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值