MultiItem進階 實現Head Foot和載入更多-多型別RecyclerView Adapter

free46000發表於2017-03-29

前言

本文是MultiItem系列的進階文章,主要講解header footer和下拉重新整理載入更多功能的用法與實現詳解,上篇文章MultiItem用法與詳解-優雅的實現多型別RecyclerView Adapter講解了一些基本的用法和依賴方式,沒有看過的同學可以點選檢視。
MutliItem主要解決多型別RecyclerView Adapter問題,在正常使用中做到了Adapter零編碼,解放了複雜的Adapter類,提高擴充套件性。
本庫的定位並不是大而全,但是會盡量做到簡單實用。

原始碼地址

Github地址:github.com/free46000/M…,請大家多多關注,更多更新會首先在GitHub上體現,也會在第一時間在本平臺釋出

效果截圖

圖片做過處理一張10幾kb

MultiItem進階 實現Head Foot和載入更多-多型別RecyclerView Adapter
headfoot

MultiItem進階 實現Head Foot和載入更多-多型別RecyclerView Adapter
fullspan

MultiItem進階 實現Head Foot和載入更多-多型別RecyclerView Adapter
loadmore

用法

新增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"));複製程式碼

充滿寬度詳見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即可。

詳解

主要利用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();
}複製程式碼

希望大家會喜歡,多多留言交流

相關文章