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列表檢視。
相關文章
- Android 給RecyclerView新增頭部和尾部AndroidView
- 在Android與recyclerview中使用列表和網格AndroidView
- 自定義圖示列表
- 自定義進度條列表
- 聊聊android列表檢視的快取設計Android快取
- Android使用RecyclerView實現二級列表AndroidView
- Android recyclerview刪除item重新整理列表AndroidView
- Android自定義標籤列表控制元件LabelsView解析Android控制元件View
- 封裝RecyclerView,實現新增頭部和底部封裝View
- android利用recyclerview展示帶有日期的圖片列表AndroidView
- iOS開發UI篇--使用UICollectionView實現一個列表頭部拉伸效果的案例iOSUIView
- 列表(recyclerView、listView及其相關)View
- 微信小程式-檢視列表渲染微信小程式
- Part 5: 任務列表檢視
- 列表檢視控制元件(轉)控制元件
- jquery如何在li元素列表的開頭新增一個新li元素jQuery
- 如何檢查 Linux 中的開放埠列表?Linux
- Flutter 自定義列表以及本地圖片引用Flutter地圖
- Android中水波紋使用之自定義檢視實現Android
- 列表與字典中的坑
- 視訊直播app原始碼,Android RecyclerView 列表載入圖片寬高適配APP原始碼AndroidView
- 如何使用Android自定義複合檢視Android
- 在表格中設定尾部檢視時,記得把顏色帶上
- css自定義列表計數程式碼例項CSS
- 自定義檢視指令
- RecyclerView進階(一)RecyclerView實現雙列表聯動View
- ReactJS新聞 #21 React Native中更好的列表檢視JSReact Native
- android短視訊開發,自定義下拉選單Android
- 直播app開發,Android ListView好友列表展示APPAndroidView
- Android 列表(ListView、RecyclerView)不斷重新整理最佳實踐AndroidView
- odoo 給列表檢視新增按鈕實現資料檔案匯入Odoo
- 學習Swift開發的免費視訊教程列表Swift
- Android開發自定義View之滑動按鈕與自定義屬性AndroidView
- (八)列表頁開發
- RecyclerView進階之層疊列表(上)View
- RecyclerView進階之層疊列表(下)View
- 看得見的資料結構Android版之陣列表(檢視篇)資料結構Android陣列
- solaris下檢視OS版本及Patch列表