RecyclerView添加Header

钱渊
2023-12-01

添加header的思路就是通过adapter的itemType来加载不同的布局。
又根据LayoutManager有不同的处理方式。
1、线性布局LinearLayoutManager
简单,只需要根据不同的itemType处理不同的ViewHolder就能实现。
设置布局管理器:
RecyclerView.LayoutManager manager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
        rv.setLayoutManager(manager);
        rv.setAdapter(new MyAdapter(arrays));
不同的viewHolder:
static class MyHolder extends RecyclerView.ViewHolder{
        public TextView tv;
        public MyHolder(View itemView) {
            super(itemView);
            tv = (TextView) itemView.findViewById(R.id.tv_rv_header_item);
        }
    }

    static class MyHeaderHolder extends RecyclerView.ViewHolder{
        public ImageView iv;
        public MyHeaderHolder(View itemView) {
            super(itemView);
            iv = (ImageView) itemView.findViewById(R.id.iv_rv_header_header);
        }
    }
复写adapter的getItemViewType方法:
@Override
        public int getItemViewType(int position) {
            return position == 0 ? ITEM_TYPE.HEADER.ordinal():ITEM_TYPE.NORMAL.ordinal();
        }
在adapter的onCreateViewHolder中根据itemType生成不同的holder:
@Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            RecyclerView.ViewHolder holder;
            if(viewType == ITEM_TYPE.HEADER.ordinal()){
                holder = new MyHeaderHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_header_header,parent,false));
            }else{
                holder = new MyHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_header_item, parent, false));
            }
            return holder;
        }
这样默认第0行就是headerView了。

2、表格布局GridLayoutManager的情况。
需要用到GridLayoutManager的setSpanSizeLookup这个方法,这个方法需要传入一个抽象类 SpanSizeLookup,在这个类中实现 getSpanSize方法。这个方法的返回值决定了我们每个position上的item占据的单元格个数,比如设置了manager是2列数据,那么header所在的item就需要占据两个单元格:
 GridLayoutManager manager = new GridLayoutManager(this,2);
        rv.setLayoutManager(manager);
复写adapter的onAttachToRecyclerView,这个方法是adapter设置给了recyclerView时回调的,在该方法里面可以得到具体的manager,通过这个manager来处理item的占据单元格的问题:
@Override
        public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
            super.onAttachedToRecyclerView(recyclerView);
            RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
            if(manager instanceof GridLayoutManager){
                final GridLayoutManager gridLayoutManager = (GridLayoutManager) manager;
                gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                    @Override
                    public int getSpanSize(int position) {
                        return getItemViewType(position)==ITEM_TYPE.HEADER.ordinal()? gridLayoutManager.getSpanCount():1;
                    }
                });
            }
        }
先判断是否是表格布局,是的话就根据itemType返回item所占的单元格。

3、瀑布流布局StaggeredGridLayoutManager的情况
又需要重写adapter的另外一个方法onViewAttachToWindow。这里的处理方式是用通过 LayoutParams,而且这里更简单, StaggeredGridLayoutManager.LayoutParams为我们提供了一个 setFullSpan方法来设置占领全部空间。
@Override
        public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
            super.onViewAttachedToWindow(holder);
            ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
            if(lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams){
                StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) lp;
                layoutParams.setFullSpan(holder.getLayoutPosition()==0);
            }
        }


 类似资料: