Android RecyclerView添加頭部和底部的方法
如果只是想添加頭部,可是使用GitHub里面這個(gè)項(xiàng)目,它可以為LinearLayoutManager,GridLayoutManager ,StaggeredGridLayoutManager布局的RecyclerView添加header。使用起來也十分簡單;
只需將RecyclerViewHeader布局放在RecyclerView的上層。
<FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|top" /> <com.bartoszlipinski.recyclerviewheader.RecyclerViewHeader android:id="@+id/header" android:layout_width="match_parent" android:layout_height="100dp" android:layout_gravity="center_horizontal|top"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="header"/> </com.bartoszlipinski.recyclerviewheader.RecyclerViewHeader> </FrameLayout>
然后獲得RecyclerViewHeader對(duì)象:
RecyclerViewHeader header = (RecyclerViewHeader) findViewById(R.id.header);
把RecyclerViewHeader賦予RecyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); // set LayoutManager for your RecyclerView header.attachTo(recyclerView, true);
注意事項(xiàng)
RecyclerViewHeader必須在RecyclerView設(shè)置了LayoutManager之后調(diào)用。
目前該庫適用于LinearLayoutManager,StaggeredGridLayoutManager和GridLayoutManager布局的RecyclerViews。只支持垂直布局LayoutManager。如果你打算在RecyclerView中使用setOnScrollListener(…)方法,確保在setOnScrollListener(…)的attachTo(…)方法之前使用。
當(dāng)然我們也可以自己寫一個(gè)添加頭部和底部的RecyclerView。它實(shí)現(xiàn)的基本原理也是通過getItemViewType方法返回不同的類型來添加頭部和底部。
首先我們自定義一個(gè)RecyclerView:
public class WrapRecyclerView extends RecyclerView { public ArrayList<View> mHeaderViews = new ArrayList<>(); public ArrayList<View> mFooterViews = new ArrayList<>(); //添加Adapter public Adapter mAdapter; public WrapRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public WrapRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); } public WrapRecyclerView(Context context) { super(context); } public void addHeaderView(View view){ mHeaderViews.clear(); mHeaderViews.add(view); if(mAdapter!=null){ if(!(mAdapter instanceof RecyclerWrapAdapter)){ mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFooterViews,mAdapter); } } } public void addFooterView(View view){ mFooterViews.clear(); mFooterViews.add(view); if(mAdapter!=null){ if(!(mAdapter instanceof RecyclerWrapAdapter)){ mAdapter = new RecyclerWrapAdapter(mHeaderViews,mFooterViews,mAdapter); } } } public void setAdapter(Adapter adapter){ if (mHeaderViews.isEmpty()&&mFooterViews.isEmpty()){ super.setAdapter(adapter); }else { adapter = new RecyclerWrapAdapter(mHeaderViews,mFooterViews,adapter) ; super.setAdapter(adapter); } mAdapter = adapter ; } }
我們會(huì)看到我們有一個(gè)RecyclerWrapAdapter沒有實(shí)現(xiàn),下面我們就來看下RecyclerWrapAdapter,這個(gè)也是實(shí)現(xiàn)添加頭部和尾部的關(guān)鍵。
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 (mFootViews == null) { this.mFootViews = EMPTY_INFO_LIST; } else { this.mFootViews = mFootViews; } } public int getHeadersCount() { return mHeaderViews.size(); } public int getFootersCount() { return mFootViews.size(); } @Override public 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); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //如果頭部不為空,那么我們就要先添加頭部,所以我們只要 //把前面幾個(gè)position給頭部,當(dāng)position小于頭部總數(shù)的時(shí)候, //我們返回頭部view。再判斷原Adapter 的 count 與當(dāng)前 position // 的差值來比較,是調(diào)用原 Adapter 的 getView 方法,還是獲取 footView // 的 view。 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; } } } @Override public int getItemCount() { if (mAdapter != null) { return getHeadersCount() + getFootersCount() + mAdapter.getItemCount(); } else { return getHeadersCount() + getFootersCount(); } } @Override public RecyclerView.Adapter getWrappedAdapter() { return mAdapter; } @Override public int getItemViewType(int position) { //增加兩個(gè)類型 //RecyclerView.INVALID_TYPE 添加頭部 //RecyclerView.INVALID_TYPE-1 添加尾部 //如果頭部不為空,那么我們就要先添加頭部,所以我們只要 //把前面幾個(gè)position給頭部,當(dāng)position小于頭部總數(shù)的時(shí)候, //我們返回頭部類型。再判斷原Adapter 的 count 與當(dāng)前 position // 的差值來比較,是調(diào)用原 Adapter 的 類型,還是獲取 footView // 的類型。 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; } private static class HeaderViewHolder extends RecyclerView.ViewHolder { public HeaderViewHolder(View itemView) { super(itemView); } } }
我們還可以實(shí)現(xiàn)一個(gè)接口,來調(diào)用RecyclerWrapAdapter對(duì)象:
public interface WrapperAdapter { public RecyclerView.Adapter getWrappedAdapter() ; }
這樣我們就可以把RecyclerView布局改成WrapRecyclerView就可以了,然后調(diào)用addHeaderView或者addFooterView就可以添加頭部和尾部了。
以上就是本文的全部內(nèi)容,希望對(duì)大家學(xué)習(xí)Android 軟件編程有所幫助。
相關(guān)文章
Android實(shí)現(xiàn)可點(diǎn)擊的幸運(yùn)大轉(zhuǎn)盤
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)可點(diǎn)擊的幸運(yùn)大轉(zhuǎn)盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02Android將應(yīng)用調(diào)試log信息保存在SD卡的方法
Android將應(yīng)用調(diào)試log信息保存在SD卡的方法大家都知道嗎,下面腳本之家小編給大家分享Android將應(yīng)用調(diào)試log信息保存在SD卡的方法,感興趣的朋友參考下2016-04-04photoView實(shí)現(xiàn)圖片多點(diǎn)觸控效果
這篇文章主要為大家詳細(xì)介紹了photoView實(shí)現(xiàn)圖片多點(diǎn)觸控效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12android播放視頻時(shí)在立體聲與單聲道之間切換無變化原因分析及解決
使用第三方視頻播放器,有立體聲與單聲道之間切換,發(fā)現(xiàn)切換后無作用,原因是由于在HAL層默認(rèn)沒有處理上層發(fā)的stereo 轉(zhuǎn)mono的命令,具體的解決方法如下2013-06-06Android實(shí)現(xiàn)滑動(dòng)刻度尺效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)滑動(dòng)刻度尺效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06Android那兩個(gè)你碰不到但是很重要的類之ViewRootImpl
這兩個(gè)類就是ActivityThread和ViewRootImpl,之所以說碰不到是因?yàn)槲覀儫o法通過正常的方式引用這兩個(gè)類或者其類的對(duì)象,本文就嘗試從幾個(gè)我們經(jīng)常接觸的方面先談?wù)刅iewRootImpl,感興趣的可以參考閱讀下2023-05-05Flutter開發(fā)實(shí)現(xiàn)底部留言板
這篇文章主要為大家詳細(xì)介紹了Flutter開發(fā)實(shí)現(xiàn)底部留言板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03Android提高之SQLite分頁讀取實(shí)現(xiàn)方法
這篇文章主要介紹了Android的SQLite分頁讀取實(shí)現(xiàn)方法,在Android項(xiàng)目開發(fā)中非常實(shí)用,需要的朋友可以參考下2014-08-08Flutter?點(diǎn)擊兩次退出app的實(shí)現(xiàn)示例
本文主要介紹了Flutter?點(diǎn)擊兩次退出app的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05