前言
本文是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();
}
希望大家会喜欢,多多留言交流