Android開發---在RecyclerView列表中新增自定義的列表頭部與尾部檢視
參考資料
前言
基本思路:
首先,頭部和尾部也是列表的一部分,它們的新增方式應該和列表中顯示資料的主體部分沒有太多區別。除了其本身使用了新的佈局檢視片段。
RecyclerView中管理的檢視項應該與資料列表中的資料保持一一對應的關係。
基於以上兩點,可以找到一種實現方式,即:通過增加兩條資料,讓檢視可以多建立兩個檢視項;將多出的兩個檢視項分別採用頭部與尾部檢視的佈局來生成。這就可以得到一個帶有自定義頭部與尾部的列表檢視。
以下的例子基於以上思路,需要修改與RecyclerView相關的框架程式碼,主要是介面卡adapter程式碼,資料來源DataSource程式碼。
實現RecyclerView展示列表(沒有頭部與尾部)的基本程式碼來自於上方參考資料 android–使用RecyclerView及相關架構元件實現列表資料展示 ,頭部與尾部的實現在此程式碼基礎之上修改。
加入頭部與尾部
先建立好用於顯示頭部與尾部的layout佈局檔案。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Here is the header"
android:textSize="18dp" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Here is the tail"
android:textSize="18dp" />
</LinearLayout>
接下來,分別調整相關的功能框架程式碼。
首先需要調整一下列表項的欄位,在列表項中增加一個欄位標記該物件是正常資料項,或是作為佔位用的頭部/尾部的空資料項。如下所示,新增了欄位pos,用於標記。
public class ItemInfo {
//字串,用於在textView中顯示
public String str;
//圖片連結,用於顯示圖片
public String imgUrl;
//一個唯一標識,可以作為列表項的鍵
public String key;
//頭-"head",尾-"tail",正常資料-null
public String pos;
}
然後,需要修改資料來源DataSource程式碼。需要實現的效果是,確保第一條資料是頭部的佔位資料。在翻頁載入資料直到所有資料載入完成之後,再傳一條尾部的佔位資料。
public class MyDataSource extends ItemKeyedDataSource<String, ItemInfo> {
private int pageIndex=1;
private boolean addTail=false;//是否已經加入尾部
private boolean addHead=false;//是否已經加入頭部
@Override
public void loadInitial(@NonNull LoadInitialParams<String> params, @NonNull LoadInitialCallback<ItemInfo> callback) {
fetchItems(params.requestedInitialKey,params.requestedLoadSize,pageIndex,callback);
}
private void fetchItems(String requestedInitialKey, int requestedLoadSize,int pageIndex,LoadCallback<ItemInfo> callback)
{
try
{
//在此處寫入獲取當前頁列表資料的程式碼,可以從資料庫中獲取,或者從後端伺服器API獲取
//List<ItemInfo> itemInfoList=*******
//callback.onResult(itemInfoList);//通過回撥返回列表資料
if (!addHead)
{
ArrayList<ItemInfo> headList=new ArrayList<ItemInfo>();
ItemInfo tail=new ItemInfo();
tail.pos="tail";
headList.add(tail);
addHead=true;
callback.onResult(headList);
return;
}
List<ItemInfo> itemInfoList=new ArrayList<ItemInfo>();
RetrofitSigleton retrofitSigleton=new RetrofitSigleton();
Response<List<ItemInfo>> response= retrofitSigleton.getService().ImgAndTextList(String.valueOf(pageIndex)).execute();
itemInfoList=response.body();
if (itemInfoList.size()==0)//沒有資料返回,已經可以加入尾部資料
{
if (!addTail)//還沒有返回尾部資料,該程式碼塊僅執行一次
{
ArrayList<ItemInfo> tailList=new ArrayList<ItemInfo>();
ItemInfo tail=new ItemInfo();
tail.pos="tail";
tailList.add(tail);
addTail=true;
callback.onResult(tailList);
return;
}
}
pageIndex=pageIndex+1;
callback.onResult(itemInfoList);
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void loadAfter(@NonNull LoadParams<String> params, @NonNull LoadCallback<ItemInfo> callback) {
try {
pageIndex=pageIndex+1;
fetchItems(params.key, params.requestedLoadSize,pageIndex,callback);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void loadBefore(@NonNull LoadParams<String> params, @NonNull LoadCallback<ItemInfo> callback) {
}
@NonNull
@Override
public String getKey(@NonNull ItemInfo item) {
return item.key;
}
}
最後,需要修改列表的介面卡程式碼。需要重寫getItemViewType()方法,對頭部,尾部返回不同的值,用於區分檢視型別。然後生成列表項檢視的時候根據viewType來載入不同的檢視佈局。
public class MyListAdapter extends PagedListAdapter<ItemInfo,MyListAdapter.ViewHolder> {
public MyListAdapter()
{
super(DIFF_CALLBACK);
}
private final int bodyItemViewType=0;
private final int tailItemViewType=1;
private final int headItemViewType=2;
private static DiffUtil.ItemCallback<ItemInfo> DIFF_CALLBACK =
new DiffUtil.ItemCallback<ItemInfo>() {
@Override
public boolean areItemsTheSame(@NonNull ItemInfo oldItem, @NonNull ItemInfo newItem) {
// The ID property identifies when items are the same.
return oldItem.key == newItem.key;
}
@Override
public boolean areContentsTheSame(@NonNull ItemInfo oldItem, @NonNull ItemInfo newItem) {
// Don't use the "==" operator here. Either implement and use .equals(),
// or write custom data comparison logic here.
return oldItem.key.equals(newItem.key);
}
};
@NonNull
@Override
public MyListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
if (viewType==this.headItemViewType)
{
view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_header_of_list,parent,false);
}
else if(viewType==this.tailItemViewType)
{
view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_tail_of_list,parent,false);
}
else {
view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_list_item,parent,false);
}
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyListAdapter.ViewHolder holder, int position) {
try {
ItemInfo _itemInfo=getItem(position);
if (_itemInfo.pos==null)
{
holder._textView.setText(_itemInfo.str);
Glide.with(holder.mView).load(_itemInfo.imgUrl).into(holder._imageView);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public int getItemViewType(int position) {
if (getItem(position).pos=="head")
{
return this.headItemViewType;
}
else if(getItem(position).pos=="tail")
{
return this.tailItemViewType;
}
else {
return this.bodyItemViewType;
}
}
public class ViewHolder extends RecyclerView.ViewHolder
{
public final ImageView _imageView;
public final TextView _textView;
public final View mView;
public ViewHolder(@NonNull View itemView)
{
super(itemView);
_textView=(TextView)itemView.findViewById(R.id.idOfTextView);
_imageView=(ImageView)itemView.findViewById(R.id.idOfImageView);
mView=itemView;
}
}
}
經過以上工作,可以實現展示一個帶有簡單頭部與尾部的RecyclerView列表檢視。
相關文章
- iOS開發-列表檢視的基本介紹與使用iOS
- 聊聊android列表檢視的快取設計Android快取
- Android recyclerview刪除item重新整理列表AndroidView
- Java 列表元素自定義排序Java排序
- Android開發 - 使用自定義介面在新視窗中傳回資料Android
- 如何檢查 Linux 中的開放埠列表?Linux
- Android 列表(ListView、RecyclerView)不斷重新整理最佳實踐AndroidView
- 視訊直播app原始碼,Android RecyclerView 列表載入圖片寬高適配APP原始碼AndroidView
- 單據列表呼叫自定義SQL函式SQL函式
- Flutter 自定義列表以及本地圖片引用Flutter地圖
- 直播app開發,Android ListView好友列表展示APPAndroidView
- iOS開發UI篇--使用UICollectionView實現一個列表頭部拉伸效果的案例iOSUIView
- android短視訊開發,自定義下拉選單Android
- 看得見的資料結構Android版之陣列表(檢視篇)資料結構Android陣列
- Android 最簡單的自定義檢視管理之一Android
- 列表與字典中的坑
- Qt Quick 訊息列表檢視元件QTUI元件
- android短視訊開發,仿三方軟體列表滑動Android
- Android RecyclerView實現頭部懸浮吸頂效果AndroidView
- 自定義檢視指令
- Android 端如何新增自定義表情Android
- 在Android Studio 中新增自定義活動模版(Live templates)Android
- Android 從零開始實現RecyclerView分組及粘性頭部效果AndroidView
- odoo 給列表檢視新增按鈕實現資料檔案匯入Odoo
- 在Luminar 4中向天空新增自定義物件物件
- CommMonitor列表檢視有什麼功能特性?
- Flutter - Drawer 抽屜檢視與自定義headerFlutterHeader
- Android進階:自定義視訊播放器開發(上)Android播放器
- Android進階:自定義視訊播放器開發(下)Android播放器
- Android開發 - inflate方法與建立檢視解析Android
- android開發(3):列表listview的實現 | 下拉重新整理AndroidView
- Laravel 自定義檢視元件Laravel元件
- (八)列表頁開發
- Android中的RecyclerViewAndroidView
- HarmonyOS NEXT應用開發—自定義檢視實現Tab效果
- Flutter 自定義View——仿同花順自選股列表FlutterView
- jQuery將li元素插入列表開頭jQuery
- Android TV開發——RecyclerView For TVAndroidView