RecyclerView 添加頭部和尾部布局,recyclerview尾部

來源:互聯網
上載者:User

RecyclerView 添加頭部和尾部布局,recyclerview尾部

RecyclerView 出來有很長一段時間了,相信大家對它已經很熟悉了,使用過它的朋友可能都會發現一點,就是 RecyclerView 不能添加 headerView 和 footView,這就讓我們有點蛋疼了,也許你會說,沒事啊,我們可以重寫getItemViewType(int position)這個方法,讓他實現多個布局,具體實現如下:

    @Override    public int getItemViewType(int position) {        if (position == 0) {            return HEAD_VIEW;        }else{            return BODY_VIEW ;        }    }

下面的操作就不多講了,這種方法相信大家在使用 ListView 的時候就非常熟練; 那既然可以通過以上方法實現,為什麼還要寫一個可以添加 HeaderView 和 FootView 的 RecyclerView ?其實這個問題不用回答,因為 ListView 也可以通過以上方法實現,但它還是有 addHeaderView和 addFootView 的方法,不過話說回來,通過 addHeaderView 實現的添加頭部布局確實有不可代替的功能,比如,ListView 頭部圖片下拉放大動畫;在調用 adapter.notifyDataSetChanged()頭部資料是不會重新重新整理的等等。

好了,接下來才是本文的主題內容,如何? RecyclerView 添加 HeaderView 和 FootView?

無從下手?沒關係!ListView 不是已經幫我們實現了這樣的功能嗎,我們可以先看看 ListView 是如何?的,

    public void addHeaderView(View v, Object data, boolean isSelectable) {        final FixedViewInfo info = new FixedViewInfo();        info.view = v;        info.data = data;        info.isSelectable = isSelectable;        mHeaderViewInfos.add(info);        mAreAllItemsSelectable &= isSelectable;        // Wrap the adapter if it wasn't already wrapped.        if (mAdapter != null) {            if (!(mAdapter instanceof HeaderViewListAdapter)) {                mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);            }            // In the case of re-adding a header view, or adding one later on,            // we need to notify the observer.            if (mDataSetObserver != null) {                mDataSetObserver.onChanged();            }        }    }

以上方法核心代碼就是

mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);

其他可以忽略不看;這裡其實用到了一種設計模式的概念,好像是叫什麼裝飾模式吧,意思就是把原有的 Adapter 通過HeaderViewListAdapter這個封裝類重新封裝一次,把改增的地方增一增,該減的地方減一點;所以我們要關注的是HeaderViewListAdapter類是如何?的,然後再依葫蘆畫瓢畫一個封裝 RecyclerView.Adapter的封裝類!

解密HeaderViewListAdapter
這個封裝類代碼本來就不長,相信大家都能夠理解的,這裡就挑點重點講一下
1、對Adapter 的 count 進行了重新計算,這個不用多解釋吧!

    public int getCount() {        if (mAdapter != null) {            return getFootersCount() + getHeadersCount() + mAdapter.getCount();        } else {            return getFootersCount() + getHeadersCount();        }    }

2、就是getView方法,這個方法是重點,如果當前 position 的位置比 HeaderView 的數量小,那麼返回的就是 HeaderView 的 對應的 View,否則再判斷 原 Adapter 的 count 與當前 position 的差值來比較,是調用原 Adapter 的 getView 方法,還是擷取 footView 的 view;說白了這個方法的目的就是添加了頭部和尾部 View。

    public View getView(int position, View convertView, ViewGroup parent) {        // Header (negative positions will throw an IndexOutOfBoundsException)        int numHeaders = getHeadersCount();        if (position < numHeaders) {            return mHeaderViewInfos.get(position).view;        }        // Adapter        final int adjPosition = position - numHeaders;        int adapterCount = 0;        if (mAdapter != null) {            adapterCount = mAdapter.getCount();            if (adjPosition < adapterCount) {                return mAdapter.getView(adjPosition, convertView, parent);            }        }        // Footer (off-limits positions will throw an IndexOutOfBoundsException)        return mFooterViewInfos.get(adjPosition - adapterCount).view;    }

對於這個封裝類的其他方法只要注意一下就 沒問題了,那麼接下來,就是我們模仿的時刻了!
代碼非常簡單,這裡就直接上了

1、封裝類 RecyclerWrapAdapter

package moon.myapplication;

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

import java.util.ArrayList;

/**
* Created by moon.zhong on 2015/7/20.
* time : 14:10
*/
public class RecyclerWrapAdapter extends RecyclerView.Adapter implements WrapperAdapter {

private RecyclerView.Adapter mAdapter;private ArrayList<View> mHeaderViews;private ArrayList<View> mFootViews;static final ArrayList<View> EMPTY_INFO_LIST =        new ArrayList<View>();private int mCurrentPosition;public RecyclerWrapAdapter(ArrayList<View> mHeaderViews, ArrayList<View> mFootViews, RecyclerView.Adapter mAdapter) {    this.mAdapter = mAdapter;    if (mHeaderViews == null) {        this.mHeaderViews = EMPTY_INFO_LIST;    } else {        this.mHeaderViews = mHeaderViews;    }    if (mHeaderViews == null) {        this.mFootViews = EMPTY_INFO_LIST;    } else {        this.mFootViews = mFootViews;    }}public int getHeadersCount() {    return mHeaderViews.size();}public int getFootersCount() {    return mFootViews.size();}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {    if (viewType == RecyclerView.INVALID_TYPE) {        return new HeaderViewHolder(mHeaderViews.get(0));    } else if (viewType == RecyclerView.INVALID_TYPE - 1) {        return new HeaderViewHolder(mFootViews.get(0));    }    return mAdapter.onCreateViewHolder(parent, viewType);}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {    int numHeaders = getHeadersCount();    if (position < numHeaders) {        return;    }    int adjPosition = position - numHeaders;    int adapterCount = 0;    if (mAdapter != null) {        adapterCount = mAdapter.getItemCount();        if (adjPosition < adapterCount) {            mAdapter.onBindViewHolder(holder, adjPosition);            return;        }    }}@Overridepublic int getItemCount() {    if (mAdapter != null) {        return getHeadersCount() + getFootersCount() + mAdapter.getItemCount();    } else {        return getHeadersCount() + getFootersCount();    }}@Overridepublic int getItemViewType(int position) {    mCurrentPosition = position;    int numHeaders = getHeadersCount();    if (position < numHeaders) {        return RecyclerView.INVALID_TYPE;    }    int adjPosition = position - numHeaders;    int adapterCount = 0;    if (mAdapter != null) {        adapterCount = mAdapter.getItemCount();        if (adjPosition < adapterCount) {            return mAdapter.getItemViewType(adjPosition);        }    }    return RecyclerView.INVALID_TYPE - 1;}@Overridepublic long getItemId(int position) {    int numHeaders = getHeadersCount();    if (mAdapter != null && position >= numHeaders) {        int adjPosition = position - numHeaders;        int adapterCount = mAdapter.getItemCount();        if (adjPosition < adapterCount) {            return mAdapter.getItemId(adjPosition);        }    }    return -1;}@Overridepublic RecyclerView.Adapter getWrappedAdapter() {    return mAdapter;}private static class HeaderViewHolder extends RecyclerView.ViewHolder {    public HeaderViewHolder(View itemView) {        super(itemView);    }}

}

2、為 RecyclerView 添加 AddHeaderView 和 addFootView 方法,重寫 RecyclerView

package moon.myapplication;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.util.AttributeSet;import android.view.View;import java.util.ArrayList;/** * Created by moon.zhong on 2015/7/20. * time : 15:14 */public class WrapRecyclerView extends RecyclerView {    private ArrayList<View> mHeaderViews = new ArrayList<>() ;    private ArrayList<View> mFootViews = new ArrayList<>() ;    private Adapter mAdapter ;    public WrapRecyclerView(Context context) {        super(context);    }    public WrapRecyclerView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public WrapRecyclerView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public void addHeaderView(View view){        mHeaderViews.clear();        mHeaderViews.add(view);        if (mAdapter != null){            if (!(mAdapter instanceof RecyclerWrapAdapter)){                mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFootViews,mAdapter) ;//                mAdapter.notifyDataSetChanged();            }        }    }    public void addFootView(View view){        mFootViews.clear();        mFootViews.add(view);        if (mAdapter != null){            if (!(mAdapter instanceof RecyclerWrapAdapter)){                mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFootViews,mAdapter) ;//                mAdapter.notifyDataSetChanged();            }        }    }    @Override    public void setAdapter(Adapter adapter) {        if (mHeaderViews.isEmpty()&&mFootViews.isEmpty()){            super.setAdapter(adapter);        }else {            adapter = new RecyclerWrapAdapter(mHeaderViews,mFootViews,adapter) ;            super.setAdapter(adapter);        }        mAdapter = adapter ;    }}

到這裡就實現了 RecyclerView 添加頭部和尾部布局 ,用法很簡單,其他步驟都不變,只需把 RecyclerView 換成WrapRecyclerView即可。

看看

這篇文章沒有什麼創新的技術點,但卻給廣大程式員一個很好的思路:那就是模仿,最好是能自己動手,也許你看一遍就能理解,但是真正動手實踐的時候你會發現很多問題!

源碼 Download

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.