RecyclerView 添加 Footer and Header

學(xué)習(xí)了 RecyclerView 的使用后,發(fā)現(xiàn) 每個(gè)顯示 ItemView 的高度寬度,以及款式都是一樣的,很是單調(diào),于是就想著如果能兩種不同的 ItemView 間隔著顯示就好了,或者說如果頭部和底部能區(qū)別于 ItemView就好了。

首先,看看添加 頭部和底部的效果圖

20160511142236439.png

靜下來想想這樣的效果并不難實(shí)現(xiàn),在 RecyclerView 中我們的視圖都是通過RecyclerView.ViewHolder來給我提供子視圖的,而這個(gè) ViewHolder 的創(chuàng)建是由 RecyclerView.Adapter 中的onCreateViewHolder() 方法控制的,來仔細(xì)看看這個(gè)方法

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 

咦,這個(gè) viewType是什么東西???實(shí)際上這個(gè) viewType是我們可以改動(dòng)的,通過 getItemViewType() 這個(gè)方法,這也就意味著,我們可以控制 ViewHolder 的創(chuàng)建,那么這樣這個(gè)效果就容易實(shí)現(xiàn)了。

首先,我們創(chuàng)建三個(gè) RecyclerView.ViewHolder,分別命名為 HeaderHolder, ContentHolderFooterHolder,他們的實(shí)現(xiàn)實(shí)際上是一樣的,除了 TextView 的命名不一樣。來看看這三個(gè)類

public class HeaderHolder extends RecyclerView.ViewHolder {

    public TextView mHeaderText;

    public HeaderHolder(View itemView) {
        super(itemView);
        mHeaderText = (TextView) itemView.findViewById(R.id.tv_header);

    }
}

public class ContentHolder extends RecyclerView.ViewHolder {
    public TextView mContentText;

    public ContentHolder(View itemView) {
        super(itemView);
        mContentText = (TextView) itemView.findViewById(R.id.tv_content);
    }
}

public class FooterHolder extends RecyclerView.ViewHolder {

    public TextView mFooterText;

    public FooterHolder(View itemView) {
        super(itemView);
        mFooterText = (TextView) itemView.findViewById(R.id.tv_footer);
    }
}

下面就是 RecyclerView.Adapter 的實(shí)現(xiàn)了,先來看看具體代碼

public class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    public static final int HEADER_ITEM = 0;
    public static final int CONTENT_ITEM = 1;
    public static final int FOOTER_ITEM = 2;
    public List<String> mDatas;
    private Context mContext;
    private LayoutInflater mInflater;

    private int mHeaderCount = 1;
    private int mFooterCount = 1;

    private String mHeaderText = "Header";
    private String mFooterText = "Footer";

    public CustomAdapter(Context context, List<String> datas) {
        mContext = context;
        mDatas = datas;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == HEADER_ITEM) {
            return new HeaderHolder(mInflater.inflate(R.layout.recycler_header, parent, false));
        } else if (viewType == CONTENT_ITEM) {
            return new ContentHolder(mInflater.inflate(R.layout.recycler_content, parent, false));
        } else {
            return new FooterHolder(mInflater.inflate(R.layout.recycler_footer, parent, false));
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof HeaderHolder) {
            ((HeaderHolder) holder).mHeaderText.setText(mHeaderText);
        } else if (holder instanceof FooterHolder) {
            ((FooterHolder) holder).mFooterText.setText(mFooterText);
        } else if (holder instanceof ContentHolder) {
            ((ContentHolder) holder).mContentText.setText(mDatas.get(position - mHeaderCount));
        }
    }

    @Override
    public int getItemViewType(int position) {

        int count = mDatas.size();
        if (mHeaderCount != 0 && position < mHeaderCount) return HEADER_ITEM;
        else if (mFooterCount != 0 && position >= (mHeaderCount + count)) return FOOTER_ITEM;
        else return CONTENT_ITEM;
    }

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

    public void setFooterText(String footerText) {
        mFooterText = footerText;
    }

    public void setHeaderText(String headerText) {
        mHeaderText = headerText;
    }

    public void removeFooter() {
        mFooterCount = 0;
    }

    public void removeHeader() {
        mHeaderCount = 0;
    }
}

相信有了前面的分析,讓你看懂以上代碼并不困難,但是需要注意的是

if (holder instanceof ContentHolder) {
            ((ContentHolder) holder).mContentText.setText(mDatas.get(position - mHeaderCount));
}

注意這段代碼中的 get方法,不是 get(position) ,因?yàn)橛辛?mHeaderCount 的存在,如果還是設(shè)置成get(position) 會(huì)出現(xiàn)數(shù)組下標(biāo)越界錯(cuò)誤,這里設(shè)置成 get(position - mHeaderCount)) 也是為了控制添加和移除 Header 的。

好了,相信如果以上效果你能實(shí)現(xiàn),那么你也就能實(shí)現(xiàn)我們一開始說的 間隔 ItemView不同布局的問題了,只需要在 getItemViewType() 方法中進(jìn)行奇偶判斷,返回不同的 viewType 就可以了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容