给RecyclerView添加header和footer

给RecyclerView添加header和footer

在最近的项目中,需要用到recyclerview添加header和footer来实现一些效果,想了想最基本的就是重写adapter的getItemViewType的方法来实现。但由于时间问题,加上博主比较懒。。。就找了个开源库,大家可能用过,叫bookends。这里就不贴地址了,本文讲的就是对bookend的改进,来实现更好的效果。

项目中需要用到header,footer的动态显示隐藏,本以为很简单的事,使用时却出了问题。

正常状态下

这里是正常状态的效果,从用户发布以上是一个header,搜索实现从网络获取数据和从自家数据库获取数据,此时自家数据库是没数据的,recyclerview显示为空。而网络搜索显示有结果,显示在header。

可是当网络搜索结果为空时,问题出现了。

问题

如图所示,header被隐藏了,可是占用的位置却没有消失。我调用的是bookends的setHeaderVisibility方法,于是查看源码

public void setHeaderVisibility(boolean shouldShow) {
        for (View header : mHeaders) {
            header.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
        }
    }

看起来没有问题,逻辑什么的都正确,GONE后的布局不占用空间位置。找不到问题就只能靠自己了。


    public void removeAllHeaders() {
        mHeaders = new ArrayList<>();
        notifyDataSetChanged();
    }

    public void removeAllFooters() {
        mFooters = new ArrayList<>();
        notifyDataSetChanged();
    }

    public void removeHeader(int position) {
        if (position < mHeaders.size())
            mHeaders.remove(position);
        notifyDataSetChanged();
    }

    public void removeFooter(int position) {
        if (position < mHeaders.size())
            mFooters.remove(position);
        notifyDataSetChanged();
    }

当当当当,问题解决。写了四个函数。测试了下 可以动态改变header和footer了。

源代码:

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;

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

/**
 * Created by simple on 2016/12/9.
 */

public class Bookends<T extends RecyclerView.Adapter> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private final T mBase;

    private static final int HEADER_VIEW_TYPE = -1000;
    private static final int FOOTER_VIEW_TYPE = -2000;

    private List<View> mHeaders = new ArrayList<View>();
    private List<View> mFooters = new ArrayList<View>();

    public Bookends(T base) {
        super();
        mBase = base;
    }

    public T getWrappedAdapter() {
        return mBase;
    }

    public void addHeader(@NonNull View view) {
        if (view == null) {
            throw new IllegalArgumentException("You can't have a null header!");
        }
        mHeaders.add(view);
        notifyDataSetChanged();
    }

    public void addFooter(@NonNull View view) {
        if (view == null) {
            throw new IllegalArgumentException("You can't have a null footer!");
        }
        mFooters.add(view);
        notifyDataSetChanged();
    }

    public void removeAllHeaders() {
        mHeaders = new ArrayList<>();
        notifyDataSetChanged();
    }

    public void removeAllFooters() {
        mFooters = new ArrayList<>();
        notifyDataSetChanged();
    }

    public void removeHeader(int position) {
        if (position < mHeaders.size())
            mHeaders.remove(position);
        notifyDataSetChanged();
    }

    public void removeFooter(int position) {
        if (position < mHeaders.size())
            mFooters.remove(position);
        notifyDataSetChanged();
    }

    public View getHeader(int i) {
        return i < mHeaders.size() ? mHeaders.get(i) : null;
    }

    public View getFooter(int i) {
        return i < mFooters.size() ? mFooters.get(i) : null;
    }

    private boolean isHeader(int viewType) {
        return viewType >= HEADER_VIEW_TYPE && viewType < (HEADER_VIEW_TYPE + mHeaders.size());
    }

    private boolean isFooter(int viewType) {
        return viewType >= FOOTER_VIEW_TYPE && viewType < (FOOTER_VIEW_TYPE + mFooters.size());
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        if (isHeader(viewType)) {
            int whichHeader = Math.abs(viewType - HEADER_VIEW_TYPE);
            View headerView = mHeaders.get(whichHeader);
            return new RecyclerView.ViewHolder(headerView) {
            };
        } else if (isFooter(viewType)) {
            int whichFooter = Math.abs(viewType - FOOTER_VIEW_TYPE);
            View footerView = mFooters.get(whichFooter);
            return new RecyclerView.ViewHolder(footerView) {
            };

        } else {
            return mBase.onCreateViewHolder(viewGroup, viewType);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        if (position < mHeaders.size()) {
            // Headers don't need anything special

        } else if (position < mHeaders.size() + mBase.getItemCount()) {
            // This is a real position, not a header or footer. Bind it.
            mBase.onBindViewHolder(viewHolder, position - mHeaders.size());

        } else {
            // Footers don't need anything special
        }
    }

    @Override
    public int getItemCount() {
        return mHeaders.size() + mBase.getItemCount() + mFooters.size();
    }

    @Override
    public int getItemViewType(int position) {
        if (position < mHeaders.size()) {
            return HEADER_VIEW_TYPE + position;

        } else if (position < (mHeaders.size() + mBase.getItemCount())) {
            return mBase.getItemViewType(position - mHeaders.size());

        } else {
            return FOOTER_VIEW_TYPE + position - mHeaders.size() - mBase.getItemCount();
        }
    }
}

使用方法:
将自己的adapter放入。

Bookends bookends= new Bookends<>(adapter);

添加footer和header

bookends.addHeader(header);
bookends.addFooter(footer);

为recyclerview设置adapter

RecyclerView.setAdapter(bookends);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值