RecyclerView實現分組展示資訊
extends:http://blog.csdn.net/wzlyd1/article/details/52292548
前言
一直在鴻洋大神的安卓群裡水群,漸漸的loader和安卓弟等人都成長了起來,還記得當初他們清純的模樣。小L在群裡不水了,安卓弟成長為CTO了,只有我依然默默無聞,於是決定再寫部落格了,之前不寫,一是因為工作比較忙,二是因為我水平有限,簡單的不想寫,因為寫了也沒用,網上demo很多,難的自己也沒多高的造詣,寫也寫不出來,所以一直都是處於“半荒廢狀態”,當然說到底其實還是因為懶,於是今天我再次執筆,將學到的東西全部記錄下來。
效果
先上效果圖給大家看看,好有一個整體的認識
效果就是這樣的,但是不僅僅侷限於這種佈局,事實上只要是三段式佈局,都可以通過該demo的學習來實現,什麼是三段式佈局呢,就是有header -content-footer型別的佈局,畫一個圖來解釋
比如下面這個圖就可以
可以看到,用途還是很廣泛的,所以很需要我們去學習一下
怎麼去實現
gitbub上有一個很牛逼的類,但是貌似知道的人很少,名字叫做SectionedRecyclerViewAdapter ,但是今天我們不去研究她是怎麼實現的,我們來研究他怎麼用就行了
- 繼承SectionedRecyclerViewAdapter
/** * Created by lyd10892 on 2016/8/23. */ public class HotelEntityAdapter extends SectionedRecyclerViewAdapter<HeaderHolder, DescHolder, RecyclerView.ViewHolder> {public ArrayList<HotelEntity.TagsEntity> allTagList; private Context mContext; private LayoutInflater mInflater; private SparseBooleanArray mBooleanMap;//記錄下哪個section是被開啟的 public HotelEntityAdapter(Context context) { mContext = context; mInflater = LayoutInflater.from(context); mBooleanMap= new SparseBooleanArray(); } public void setData(ArrayList<HotelEntity.TagsEntity> allTagList) { this.allTagList = allTagList; notifyDataSetChanged(); } @Override protected int getSectionCount() { return HotelUtils.isEmpty(allTagList) ? 0 : allTagList.size(); } @Override protected int getItemCountForSection(int section) { int count = allTagList.get(section).tagInfoList.size(); if (count >= 8 && !mBooleanMap.get(section)) { count = 8; } return HotelUtils.isEmpty(allTagList.get(section).tagInfoList) ? 0 : count; } //是否有footer佈局 @Override protected boolean hasFooterInSection(int section) { return false; } @Override protected HeaderHolder onCreateSectionHeaderViewHolder(ViewGroup parent, int viewType) { return new HeaderHolder(mInflater.inflate(R.layout.hotel_title_item, parent, false)); } @Override protected RecyclerView.ViewHolder onCreateSectionFooterViewHolder(ViewGroup parent, int viewType) { return null; } @Override protected DescHolder onCreateItemViewHolder(ViewGroup parent, int viewType) { return new DescHolder(mInflater.inflate(R.layout.hotel_desc_item, parent, false)); } @Override protected void onBindSectionHeaderViewHolder(final HeaderHolder holder, final int section) { holder.openView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { boolean isOpen = mBooleanMap.get(section); String text = isOpen ? "展開" : "關閉"; mBooleanMap.put(section, !isOpen); holder.openView.setText(text); notifyDataSetChanged(); } }); holder.titleView.setText(allTagList.get(section).tagsName); holder.openView.setText(mBooleanMap.get(section) ? "關閉" : "展開"); } @Override protected void onBindSectionFooterViewHolder(RecyclerView.ViewHolder holder, int section) { } @Override protected void onBindItemViewHolder(DescHolder holder, int section, int position) { holder.descView.setText(allTagList.get(section).tagInfoList.get(position).tagName); } }
這裡面有幾個很重要的方法也是需要我們必須重寫的,是我們實現效果的關鍵
protected abstract int getSectionCount(); protected abstract int getItemCountForSection(int section); protected abstract boolean hasFooterInSection(int section); protected abstract H onCreateSectionHeaderViewHolder(ViewGroup parent, int viewType); protected abstract F onCreateSectionFooterViewHolder(ViewGroup parent, int viewType); protected abstract VH onCreateItemViewHolder(ViewGroup parent, int viewType); protected abstract void onBindSectionHeaderViewHolder(H holder, int section); protected abstract void onBindSectionFooterViewHolder(F holder, int section); protected abstract void onBindItemViewHolder(VH holder, int section, int position);
接下來我們詳細分析這幾個方法存在的具體意義
不過在說之前我們需要看一下我們的資料結構,這個也很重要
public class HotelEntity { /** * 要注意這個類的資料結構,很重要,直接決定了我們能不能實現分組展示 */ public ArrayList<TagsEntity> allTagsList; public class TagsEntity { public String tagsName; public ArrayList<TagInfo> tagInfoList; public class TagInfo { public String tagName; } } }
這個方法主要是用來計算我們一共有多少個section需要展示,返回值是我們最外稱list的大小,在我們的示例圖中,對應的為熱門品牌—商業區—熱門景點 等,對應的資料是我們的allTagList
protected abstract int getSectionCount();
這個方法是用來展示content內容區域,返回值是我們需要展示多少內容,在本例中,我們超過8條資料只展示8條,點選展開後就會展示全部資料,邏輯就在這裡控制。 對應資料結構為tagInfoList
protected abstract int getItemCountForSection(int section);
判斷是否需要底部footer佈局,在該例中,我們並不需要顯示footer,所以預設返回false就可以,如果你對應的section需要展示footer佈局,那麼就在對應的section返回true就行了
protected abstract boolean hasFooterInSection(int section);
我們要單獨說一下這個方法,這裡有一個section和position ,有些人可能會弄混
section是區域,也就是我們最外層的index,position是每個section對應的內容資料的position
@Override protected void onBindItemViewHolder(DescHolder holder, int section, int position) { holder.descView.setText(allTagList.get(section).tagInfoList.get(position).tagName); }
至於下面的onCreateViewHolder ,onBindViewHolder不多做解釋了,如果你用過recyclerView,使用方法是一樣的,無非是渲染布局,繫結資料
- 展示資料
基本上,如果上面的adapter邏輯寫完,我們的佈局算是完成了,首頁程式碼如下
public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private HotelEntityAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); mAdapter = new HotelEntityAdapter(this); GridLayoutManager manager = new GridLayoutManager(this,4);//我們需要網格式的佈局 //設定header佔據的空間 manager.setSpanSizeLookup(new SectionedSpanSizeLookup(mAdapter,manager)); mRecyclerView.setLayoutManager(manager); mRecyclerView.setAdapter(mAdapter); HotelEntity entity = JsonUtils.analysisJsonFile(this,"json"); mAdapter.setData(entity.allTagsList); } }
程式碼裡有一段很重要的註釋,設定header佔據的空間,沒錯,因為我們要仿造header的效果,我們設定的manager是GridLayoutManager,設定的每一行item數量是4,如果不重寫該方法,那麼header顯示就會出錯,核心程式碼如下:
/** * A SpanSizeLookup to draw section headers or footer spanning the whole width of the RecyclerView * when using a GridLayoutManager * * 這個類是用來自定義每個item需要佔據的空間 * * */ public class SectionedSpanSizeLookup extends GridLayoutManager.SpanSizeLookup { protected SectionedRecyclerViewAdapter<?, ?, ?> adapter = null; protected GridLayoutManager layoutManager = null; public SectionedSpanSizeLookup(SectionedRecyclerViewAdapter<?, ?, ?> adapter, GridLayoutManager layoutManager) { this.adapter = adapter; this.layoutManager = layoutManager; } @Override public int getSpanSize(int position) { //header和footer佔據的是全屏 if(adapter.isSectionHeaderPosition(position) || adapter.isSectionFooterPosition(position)){ return layoutManager.getSpanCount(); }else{ return 1;//其他預設1 } } }
最重要的是getSpanSize方法,只要是header或者是footer就返回我們設定的網格數,也就是4,代表header和footer佔據4個網格的空間,其他佔據1個
這樣,我們就可以完美的展示我們需要的佈局了
當前我們的demo是網格佈局的,你也可以設定流式佈局,只需要設定不同的layoutmanager就可以了
比如下圖的效果我們也可以實現
核心程式碼已經解釋完畢,當然最核心的是SectionedRecyclerViewAdapter這個類,這個類好好學習一下,會學到很多,也會實現很多app常見的佈局效果,比如設定不同的viewType展現更復雜的佈局
最後,看一下程式碼結構:
最後囉嗦一句,寫部落格比寫程式碼難多了。
demo已經上傳到github了,歡迎fork
https://github.com/nbwzlyd/SectionRecyclerViewDemo
相關推薦
RecyclerView實現分組展示資訊
extends:http://blog.csdn.net/wzlyd1/article/details/52292548 前言 一直在鴻洋大神的安卓群裡水群,漸漸的loader和安卓弟等人都成長了起來,還記得當初他們清純的模樣。小L在群裡不水了,安卓弟成長為CTO了,只有我依然默默無聞,於是決定再寫部落格了,
RecyclerView實現分組展示信息
ast 還記得 rac 算法 sem 示例 安卓 item ride extends:http://blog.csdn.net/wzlyd1/article/details/52292548 前言 一直在鴻洋大神的安卓群裏水群,漸漸的loader和安卓弟等人都成長了起來,還
用Recyclerview實現列表分組、下拉重新整理以及上拉載入--原始碼
這裡放上之前整理的一篇文章的完整原始碼,因為是從專案中抽取出來的,也沒有單獨再寫一個demo,希望需要的小夥伴能結合之前寫的一篇文章,理解實現原理,而不要簡單的想要直接copy拿來用,這裡是博文地址: import android.content.Con
用Recyclerview實現列表分組、下拉重新整理以及上拉載入更多
為什麼要使用Recyclerview替代ListView等傳統元件 目前的專案中已經逐步拋棄了ListView、GridView以及各種自定義的瀑布流效果的第三方庫了,統一用強大的替代者Recyclerview來實現。一個Recyclerview就解決了上面三
使用Recyclerview實現線性佈局和網格佈局資料展示
效果實現圖使用的依賴和許可權implementation 'com.facebook.fresco:fresco:0.12.0' implementation 'com.squareup.okhttp3:okhttp:3.4.2' implementatio
使用RecyclerView實現電商物流資訊的時光軸效果
相信RecyclerView大家已經不陌生了,最近公司專案中檢視物流資訊需要用到時光軸,所以在完成此功能之後寫下了這一篇文章,希望對大家有所幫助. 需求 要達到的效果 實現功能 需求 首先為什麼要做時光軸,用它來體現有什麼好處,現在比較大的
RecyclerView分組之BaseRecyclerViewAdapterHelper(實現分組功能)
1.前言 相信很多小夥伴之前用過listview列表展示資料,然後RecyclerView應該不會陌生,大多數開發者應該都使用上它了,它也是google推薦替換ListView的控制元件,但是用過它的同學應該都知道它在某些方面並沒有ListView使用起來方
Android使用RecyclerView實現上拉載入更多,下拉重新整理,分組顯示
專案地址:點選開啟連結(https://github.com/MrGaoGang/luckly_recyclerview) 使用RecyclerView封裝headerview,footerView,並實現上拉載入更多,下拉重新整理,分組功能(新增上拉載入和下拉
RecyclerView實現終極畫廊效果 中間突出並且壓住兩側布局
div -1 我認 with lis dsi style only his 先給大家上個gif 要不然下面很枯燥 忘記原來在哪裏看到了..... 這個效果我找了NNNNNN長時間,,,我認為憑我現在的能力 寫出來需要好久 所以 退而求其次找大神寫好的... 你們不
Android基於RecyclerView實現高亮搜索列表
新生代 gil char 能力 hub != AD listview 主動 這篇應該是RecycleView的第四篇了,RecycleView真是新生代的寵兒能做這麽
Android用RecyclerView實現的二維Excel效果組件
eight main AS UC alt 包括 data github AD excelPanel 二維RecyclerView。不僅可以加載歷史數據,而且可以加載未來的數據。 包括在您的項目中 excelPanel 二維RecyclerView。不僅可以加載
Android tabLayout+recyclerView實現錨點定位
ons boolean 根據 https set ret 需要 tco int 原文鏈接:https://mp.weixin.qq.com/s/L3o2i3WTmg1ScXEYDS8YCg 在上一篇文章 Android 實現錨點定位中,我們介紹了tablayout+sc
WaveSwipeRefreshLayout +RecyclerView 實現簡單的水滴下拉重新整理
第一步: 1.在app build.gradle中加入依賴: implementation 'com.github.recruit-lifestyle:WaveSwipeRefreshLayout:1.6' 2.AndroidManifest中新增網路許可權
一步一步實現web程式資訊管理系統之一----登陸介面實現
一步一步實現web程式資訊管理系統 在web程式中特別是資訊管理系統,登陸功能必須有而且特別重要。每一個學習程式開發或以後工作中,都會遇到實現登陸功能的需求。而登陸功能最終提供給客戶或展現給客戶的最基本的就是2個文字框一個按鈕使用者名稱與密碼,外加一個登陸按鈕。本篇記錄一下登陸功能的前端介面的實現。 1.
css定位實現星級展示沒有互動
<div class="star_evaluate"> <span class="star star_10"></span> </div> .star_evaluate{ position: relativ
RxDataSources與TableView中實現介面展示(二)
通過按鈕重新整理介面引數,設定延時為2s // ViewController.swift // RxSwiftTest // // Created by travey on 2018/11/5. // Copyright © 2018年 ZhouShijie. All rights r
RxDataSources與TableView實現介面展示(一)
// ViewController.swift // RxSwiftTest // // Created by travey on 2018/11/5. // Copyright © 2018年 ZhouShijie. All rights reserved. import UIKit
RecyclerView實現圖文混排
RecyclerView實現圖文混排 一、實現效果 二、設計思路 三、實現過程 1. 選擇圖片 2. 載入圖片 3. 顯示圖片 四、最後 一、實現效果
基於RecyclerView的分組列表
基於RecyclerView的分組列表 一、實現效果 二、使用方式 1. 建立SectionList例項 2. 新增分組 3. 資料關聯到Adapter 三、設計思路 四、程式碼分析