前言
本文是MultiItem
系列的進階文章,主要講解header footer
和下拉刷新加載更多功能的用法與實現詳解,上篇文章MultiItem用法與詳解-優雅的實現多類型RecyclerView Adapter講解了一些基本的用法和依賴方式,沒有看過的同學可以點擊查看。
MutliItem
主要解決多類型RecyclerView Adapter問題,在正常使用中做到了Adapter
零編碼,解放了復雜的Adapter
類,提高擴展性。
本庫的定位并不是大而全,但是會盡量做到簡單實用。
源碼地址
Github地址:https://github.com/free46000/MultiItem,請大家多多關注,更多更新會首先在GitHub上體現,也會在第一時間在本平臺發布
效果截圖
圖片做過處理一張10幾kb



用法
為列表添加header和footer
添加header footer
提供兩種方式,直接addView
或者addItem
方式:
//為XXBean數據源注冊XXManager管理類
adapter.register(TextBean.class, new TextViewManager());
//添加header
TextView headView = new TextView(this);
headView.setText("通過addHeadView增加的head1");
//方式一:方便實際業務使用
adapter.addHeadView(headView);
//方式二:這種方式和直接addDataItem添加數據源原理一樣
adapter.addHeadItem(new TextBean("通過addHeadItem增加的head2"));
//添加footer,方式同添加header
TextView footView = new TextView(this);
footView.setText("通過addFootView增加的foot1");
adapter.addFootView(footView);
adapter.addFootItem(new TextBean("通過addFootItem增加的foot2"));
為表格添加充滿寬度的Item(含header和footer)
充滿寬度詳見ViewHolderManager#isFullSpan
返回true
即可,適用于head foot
或任意數據源Item
//此處為TextBean數據源注冊FullSpanTextViewManager管理類
adapter.register(TextBean.class, new FullSpanTextViewManager());
//添加header或者footer
TextView headView = new TextView(this);
headView.setText("通過addHeadView增加的head1");
//使用HeadFootHolderManager已經實現isFullSpan方法,默認充滿寬度
adapter.addHeadView(headView);
//添加普通Item,詳見FullSpanTextViewManager,默認充滿寬度
adapter.addDataItem(new TextBean("FullSpanTextViewManager充滿寬度Item"));
下拉刷新加載更多功能的用法
下拉刷新采用SwipeRefreshLayout
這里就不在過多介紹,開啟和處理加載更多功能比較簡單,但是需要注意加載更多本質上是一個footer
,并且對添加順序敏感,所以需要先去addFoot
后在調用開啟方法:
//開啟加載更多視圖
adapter.enableLoadMore(new LoadMoreHolderManager(this::loadData));
//加載完成 isLoadAll:是否全部數據
adapter.setLoadCompleted(boolean isLoadAll);
//加載失敗
adapter.setLoadFailed();
通過開啟方法我們可以看出依賴于LoadMoreHolderManager
,主要是處理不同狀態下加載更多界面的變化,下面貼出代碼,更多實現細節請參閱LoadMoreManager
:
/**
* 加載更多視圖管理類
*/
public class LoadMoreHolderManager extends LoadMoreManager {
public LoadMoreHolderManager(OnLoadMoreListener onLoadMoreListener, boolean isAutoLoadMore) {
super(onLoadMoreListener, isAutoLoadMore);
}
@Override
protected int getItemLayoutId() {
return R.layout.item_load_more;
}
@Override
protected void updateLoadInitView() {
((TextView) getView(loadMoreView, R.id.text)).setText("");
}
@Override
protected void updateLoadingMoreView() {
((TextView) getView(loadMoreView, R.id.text)).setText(R.string.loading_more);
}
@Override
protected void updateLoadCompletedView(boolean isLoadAll) {
((TextView) getView(loadMoreView, R.id.text))
.setText(isLoadAll ? R.string.load_all : R.string.load_has_more);
}
@Override
protected void updateLoadFailedView() {
((TextView) getView(loadMoreView, R.id.text)).setText(R.string.load_failed);
}
}
至此本庫的header footer
和下拉刷新加載更多功能的用法已經完成,并沒有修改或繼承RecyclerView Adapter
類,完全使用默認實現BaseItemAdapter
即可。
詳解
header和footer
主要利用Multiitem
的多類型特性,封裝了實用api
而已,在BaseItemAdapter
中維護了headItems
footItems
兩個集合,在getItem
的時候根據順序獲取數據,如下:
/**
* @param position int
* @return 返回指定位置Item
*/
public Object getItem(int position) {
if (position < headItems.size()) {
return headItems.get(position);
}
position -= headItems.size();
if (position < dataItems.size()) {
return dataItems.get(position);
}
position -= dataItems.size();
return footItems.get(position);
}
為表格添加充滿寬度的Item
在ViewHolderManager
中封裝了兩個方法以適配表格布局的時候填充寬度:
/**
* @return 是否填滿父布局
* @see StaggeredGridLayoutManager.LayoutParams#setFullSpan
* @see GridLayoutManager#setSpanSizeLookup
*/
public boolean isFullSpan() {
return fullSpan;
}
/**
* 根據spanCount獲取當前所占span大小(適用于表格布局)
* 如果被設置過正整數則返回;如果是fullSpan則返回spanCount;其余返回1
* GridLayoutManager模式下,調整本方法返回值達到不同Item占用不同寬度的功能
*
* @param spanCount span總數量
* @return 當前所占span大小
* @see GridLayoutManager#setSpanSizeLookup
*/
public int getSpanSize(int spanCount) {
return spanSize > 0 ? spanSize : (isFullSpan() ? spanCount : 1);
}
加載更多
加載更多利用onBindViewHolder
這個 RecyclerView Adapter
的回調方法實現了對加載更多視圖狀態的模板方法的封裝,并提供了對應的處理方法,詳見LoadMoreManager
,這里貼出關鍵代碼:
@Override
public void onBindViewHolder(@NonNull BaseViewHolder holder, @NonNull Object o) {
if (isNeeLoadMore(holder)) {
if (isAutoLoadMore()) {
//當可以加載更多數據并開啟自動加載后調用
onLoadMore();
}
} else {
updateLoadInitView();
}
}
/**
* 避免第一次可見時去加載數據
* 若head和foot的數量小于當前loadMore的位置則證明沒有ItemData數據,即為RecyclerView加載數據前
*
* @param holder
* @return 是否需要加載更多
*/
protected boolean isNeeLoadMore(@NonNull BaseViewHolder holder) {
int headFootCount = adapter.getHeadCount() + adapter.getFootCount();
return headFootCount < holder.getItemPosition();
}
希望大家會喜歡,多多留言交流