RecyclerView系列之增加header

一、背景
在RecyclerView还没出来时,列表布局基本都是用 ListView,app 中一般都会有这种设计,上面一个 banner 轮播图,下面一个列表,特别是一些电商类,新闻类 app。
下面是最终效果:
在这里插入图片描述
向上滑动列表时,上面的轮播图就会被滑上去,显然是一体的,用 ListView 时,可以把上面的轮播图控件作为一个 HeaderView 加到 ListView 中,爽的是 ListView 的 API 中已经提供了 addHeaderView() 方法,直接使用就能实现上面的效果,不爽的是 RecyclerView 中居然没提供这个方法,体验了爽的之后再体验不爽的,那就不爽了,只能自己加咯。

二、实现方式
还是在 itemViewType 上做文章,接着上篇文章的 BaseAdapter 来修改,RecyclerView系列之加载更多
增加一个 HeaderType

...
    
@Override
public int getItemViewType(int position) {
    if (isFooterView(position)) {
        return TYPE_FOOTER_VIEW;
    }
    if (isHeaderView(position)) {
        return TYPE_HEADER_VIEW;
    }
    return TYPE_CONTENT_VIEW;
}

@Override
public int getItemCount() {
    if (null == mDatas) {
        return 0;
    }
    return mDatas.size() + getFooterViewCount() + getHeaderViewCount();
}

private boolean isHeaderView(int position) {
        return position < getHeaderViewCount();
}

protected int getHeaderViewCount() {
    if (mHeaderLayout == null || mHeaderLayout.getChildCount() == 0) {
        return 0;
    }
    return 1;
}

...

同时 getItemCount 也要增加 headerView 的个数,然后在 onCreateViewHolder 里通过 itemViewType 判断创建什么 ViewHolder

...
    
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    BaseViewHolder baseViewHolder = null;
    switch (viewType) {
        case TYPE_CONTENT_VIEW:
            baseViewHolder = BaseViewHolder.create(getLayoutId(), parent);
            break;
        case TYPE_FOOTER_VIEW:
            if (mFooterLayout == null) {
                mFooterLayout = new RelativeLayout(parent.getContext());
            }
            baseViewHolder = BaseViewHolder.create(mFooterLayout);
            break;
        case TYPE_HEADER_VIEW:
            baseViewHolder = BaseViewHolder.create(mHeaderLayout);
            break;
    }
    return baseViewHolder;
}

...

然后就可以增加 HeaderView 了

...
    
/**
 * 添加headerView
 * @param view
 * @param index
 */
public void addHeaderView(View view, int index) {
    checkHeaderLayout(view);
    int childCount = mHeaderLayout.getChildCount();
    if (index < 0 || index > childCount) {
        index = childCount;
    }
    mHeaderLayout.addView(view, index);
    if (mHeaderLayout.getChildCount() == 1) {
        notifyItemInserted(0);
    }
}

private void checkHeaderLayout(View view) {
    if (null == mHeaderLayout) {
        mHeaderLayout = new LinearLayout(view.getContext());
        mHeaderLayout.setOrientation(LinearLayout.VERTICAL);
        mHeaderLayout.setLayoutParams(new RecyclerView.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
    }
}

...

增加之前先检查下用来装 HederView 的 mHeaderLayout 是否创建,没有创建就创建出来并设置方向为竖向的,其实也可以设置成横向的,但是我还真没见过哪个 app 里有一个横向的列表还要在最左边放一个 header 的。

三、总体思路如下:
1.增加 headerView 时先在 itemCount 加 1,就是腾出一个 item 用来放 headerView;
2.getItemType 里增加 headerView 的判断,如果有 headerView 且 item 为第一个时,type 设置为 HEADER_TYPE;
3.在 onCreateViewHolder 里判断如果是 HEADER_TYPE 就创建 headerLayout 用来装 headerView,这样可以很方便的 add 多个 headerView。
到此就实现上面图中的效果了,有兴趣的可看完整源码。

源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值