国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

RecyclerView學習(1) 添加頭部和尾部

2019-11-06 09:44:56
字體:
來源:轉載
供稿:網友

轉載請注明出處 http://blog.csdn.net/u011453163/article/details/58586687

RecyclerView 已經不是一個陌生的組件了,但是相對于現在的項目在還是用比較老舊的ListView,雖然功能都能實現,但是畢竟得跟上時代變化嘛。

關于RecyclerView添加 頭部和尾部,網上已經有各種大牛的版本,實現起來也不是很難。但是看一遍不如擼一遍。這里對學習RecyclerView過程中做一些記錄,部分實現也有借鑒大牛們的思路,見笑。

先上個簡單的效果圖。

這里寫圖片描述

RecyclerView不像ListView 一樣 提供了添加頭部和尾部的方法,但是RecyclerView和ListView一樣是支持多類型Item布局的,那么反過來 頭部和尾部 也就只是一些特定類型的布局而已。所以我們可以通過 public int getItemViewType(int position) 算出頭部和尾部的Type 來加載頭部和尾部。

這里通過兩種方式來實現這個效果,思路是一樣的。

自定義一個 ExpandAdapter 繼承 RecyclerView.Adapter

public class ExpandAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { PRivate RecyclerView.Adapter<RecyclerView.ViewHolder> adapter; public ExpandAdapter(RecyclerView.Adapter<RecyclerView.ViewHolder> adapter) { this.adapter = adapter; } @Override public int getItemViewType(int position) { return adapter.getItemViewType(position); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return adapter.onCreateViewHolder(parent, viewType); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { adapter.onBindViewHolder(holder, position); } @Override public int getItemCount() { return adapter.getItemCount(); } }

這里只是簡單的做一個轉換工作,以方便后期使用不需要去改動太多的東西。 1 通過 List 來實現。 接下來開始分析實現思路,首先要注意的是 public int getItemViewType(int position)默認是返回 0 的, 所以在定義頭部和尾部的type是要錯開 0 ,網上大部分大牛的思路都是定義一個比較大的起始值。

1 一個較大的起始值

private static final int TPEY_COUNT_START_TAG =100000;

2 兩個存儲頭部和尾部 view的集合,和添加頭部和尾部對應的方法

List<View> headViews = new ArrayList<>(); List<View> footViews = new ArrayList<>(); public void addHeadView(View v) { if (headViews != null) { v.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); headViews.add(v); } } public void addFootView(View v) { if (footViews != null) { v.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); footViews.add(v); } }

3 在 public int getItemViewType(int position) 計算返回的type

public int getItemViewType(int position) { if (headViews.size() > 0) { if (position < headViews.size()) { return position+ TPEY_COUNT_START_TAG; } } if (footViews.size() > 0) { if (position >= getItemCount() - footViews.size()) { return position+ TPEY_COUNT_START_TAG; } } return adapter.getItemViewType(position); }

因為這里只有一個position參數可以使用,所以在position的基礎上加個一個較大的值,這里是加法之后我們要做減法來算出下標 取出對應的 頭部view和尾部view。

4 從List中取出渲染對應的頭部和尾部。

定義頭部和尾部對應的ViewHolder 便于理解

class HeaderHolder extends RecyclerView.ViewHolder { public HeaderHolder(View itemView) { super(itemView); } } class FootHolder extends RecyclerView.ViewHolder { public FootHolder(View itemView) { super(itemView); } }@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (headViews.size() > 0) { if (viewType- TPEY_COUNT_START_TAG >= 0 && viewType- TPEY_COUNT_START_TAG < headViews.size()) { return new HeaderHolder(headViews.get(viewType- TPEY_COUNT_START_TAG)); } } if (footViews.size() > 0) { Log.d("ExpandAdapter", "viewType:" + viewType); if (viewType- TPEY_COUNT_START_TAG >= getItemCount() - footViews.size() && viewType- TPEY_COUNT_START_TAG < getItemCount()) { return new FootHolder(footViews.get(viewType- TPEY_COUNT_START_TAG -adapter.getItemCount()-headViews.size())); } } return adapter.onCreateViewHolder(parent, viewType); }

這里主要就是做一些判斷 算出下標 來取出 headViews, footViews中對應的view。

5 綁定數據

@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(holder instanceof FootHolder ||holder instanceof HeaderHolder){ return; } adapter.onBindViewHolder(holder, position); } @Override public int getItemCount() { return adapter.getItemCount() + headViews.size() + footViews.size(); }

動態添加的頭部和尾部不需要在適配器里渲染數據,所以直接返回不管。Item總數就是頭部和尾部和普通itme的總和,這個沒必要說的。

6.由于RecyclerView 的布局形式不同。GridLayoutManager,StaggeredGridLayoutManager,LinearLayoutManager。為了適配這三者,還需要重寫兩個方法,這個是借鑒網上大牛的。

@Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { adapter.onViewAttachedToWindow(holder); int position = holder.getLayoutPosition(); if ((position >= 0 && position < headViews.size())||(position>=getItemCount()-footViews.size()&&position<getItemCount())) { ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) { StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; p.setFullSpan(true); } } } @Override public void onAttachedToRecyclerView(final RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); if (recyclerView.getLayoutManager() instanceof GridLayoutManager) { ((GridLayoutManager) recyclerView.getLayoutManager()).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (position >= 0 && position < headViews.size()) { return ((GridLayoutManager) recyclerView.getLayoutManager()).getSpanCount(); }else if(position>=getItemCount()-footViews.size()&&position<getItemCount()){ return ((GridLayoutManager) recyclerView.getLayoutManager()).getSpanCount(); } else { return 1; } } }); } }

StaggeredGridLayoutManager

這里寫圖片描述

GridLayoutManager

這里寫圖片描述

以上是使用List實現的方式,第二種的思路也是一樣的,通過兩個HashMap來存儲頭部和尾部 ,就不詳細介紹了,主要列出一些區別。

private static final int TPEY_HEADER_STATRT_INDEX =-100000; private static final int TPEY_FOOT_START_INDEX =100000; HashMap<Integer,View> headViewss=new HashMap<>(); HashMap<Integer,View> footViewss=new HashMap<>(); /**添加頭部*/ public void addHeadView(View v) { if(headViewss!=null){ v.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); headViewss.put(TPEY_HEADER_STATRT_INDEX+headViewss.size(),v); } } /**添加頭部*/ public void addFootView(View v) { if(footViewss!=null){ v.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); footViewss.put(TPEY_FOOT_START_INDEX+footViewss.size(),v); } }/**重寫適配器的兩個方法也有區別 這里也可以同set 返回key值*/ @Override public int getItemViewType(int position) { if(headViewss!=null&&position<headViewss.size()){ return position+TPEY_HEADER_STATRT_INDEX; } if(footViewss!=null&&position>=adapter.getItemCount()+headViewss.size()){ return TPEY_FOOT_START_INDEX+(position-adapter.getItemCount()-headViewss.size()); } return adapter.getItemViewType(position); } /**通過Key直接獲取*/ @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if(headViewss.containsKey(viewType)){ return new HeaderHolder(headViewss.get(viewType)); } if(footViewss.containsKey(viewType)){ return new FootHolder(footViewss.get(viewType)); } return adapter.onCreateViewHolder(parent, viewType); }/**此方法基本一樣*/ @Override public int getItemCount() { return adapter.getItemCount() + headViewss.size() + footViewss.size(); }

這里因為是使用了ExpandAdapter 來做一個包裝,所以相應的使用一個自定義RecyclerView來實現。以便我們不用做太多的改動。

public class ExpandRecyclerView extends RecyclerView{ ExpandAdapter expandAdapter; public ExpandRecyclerView(Context context) { super(context); } public ExpandRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public ExpandRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void setAdapter(Adapter adapter) { expandAdapter =new ExpandAdapter(adapter); super.setAdapter(expandAdapter); } public void addHeadView(View v){ if(expandAdapter !=null){ expandAdapter.addHeadView(v); expandAdapter.notifyDataSetChanged(); } } public void addFootView(View v){ if(expandAdapter !=null){ expandAdapter.addFootView(v); expandAdapter.notifyDataSetChanged(); } }}

使用自定義RecyclerView之后 我們不需要去改動適配器 還是該怎么使用就怎么使用。

到此,RecyclerView的添加頭部和尾部就結束了。有什么不對的地方望指正。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 秦安县| 东源县| 萨迦县| 重庆市| 秀山| 永清县| 中江县| 东阳市| 积石山| 包头市| 朝阳县| 青田县| 通山县| 田东县| 罗平县| 龙川县| 子洲县| 吉首市| 安乡县| 大兴区| 柯坪县| 南乐县| 西乡县| 布尔津县| 姚安县| 绥化市| 常德市| 当雄县| 柳州市| 江川县| 河源市| 南靖县| 沙洋县| 枣阳市| 鄱阳县| 绥棱县| 曲沃县| 汉源县| 东宁县| 阿坝县| 彭水|