为RecyclerView提供更简单的适配器实现方式,不断更新完善中。
Demo视频演示
GitHub地址
博客
yourProject.gradle
文件中添加如下代码进行依赖 allprojects {
repositories {
maven { url 'https://dl.bintray.com/chendongmarch/maven' }
}
}
yourApp.gradle
文件中添加依赖 compile 'com.march.lib-adapter:lib-adapter:1.0.0'
SparseArray
实现View的缓存。//BaseViewHolder
//获取控件
public T getView(int resId)
public T getView(String resId)
//设置可见
public RvViewHolder setVisibility(int resId, int v)
//文字
public RvViewHolder setText(int resId, String txt)
//图片
public RvViewHolder setImg(int resId, int imgResId)
//监听
public RvViewHolder setClickLis(int resId, View.OnClickListener listener)
//一个简单的实现,实体类不需要再去实现RvQuickInterface接口
SimpleRvAdapter simpleAdapter =
new SimpleRvAdapter(self, demos, R.layout.rvquick_item_a) {
@Override
public void onBindView(RvViewHolder holder, Demo data, int pos) {
holder.setText(R.id.item_a_tv, data.title);
}
};
TypeRvAdapter
多类型数据适配时需要接受ITypeAdapterModel(接口)
类型的的数据,因此进行多类型数据适配时,你的Model需要实现ITypeAdapterModel
告知Adapter数据的type
addType(int type,int res)
方法用来给每种类型的数据添加不同的布局文件,达到多类型适配的目的。
// Demo类必须实现 ITypeAdapterModel 接口
TypeRvAdapter typeAdapter =
new TypeRvAdapter(context, data) {
@Override
public void onBindView(RvViewHolder holder, Demo data, int pos, int type) {
//根据类型绑定数据
switch (type) {
case Demo.CODE_DETAIL:
holder.setText(R.id.item_quickadapter_type_title, data.getmDemoTitle()).setText(R.id.item_quickadapter_desc, data.getmDescStr());
break;
case Demo.JUST_TEST:
holder.setText(R.id.item_quickadapter_title, data.getmDemoTitle());
break;
}
}
};
typeAdapter.addType(Demo.CODE_DETAIL, R.layout.item_layout_a)
.addType(Demo.JUST_TEST, R.layout.item_layout_b);
SectionRvAdapter
作为ItemHeader的数据类型需要继承AbsSectionHeader(抽象类)
class ItemHeader extends AbsSectionHeader {
String itemHeaderTitle;
}
class Content {
int contentIndex
String contentTitle;
}
ISectionRule接口
,进行九宫格模式适配使用 ISectionRule 配置数据时,需要添加ISectionRule
,这是一种规则,adapter会根据你提供的规则自动生成Header
提供了两种构造方法
// 直接配置 item header 和 content 的 layout 资源
public SectionRvAdapter(Context context,List originDatas,
int headerLayoutId, int contentLayoutId)
// 只添加 header 的 layout 资源,content的资源可以使用addType方法添加
public SectionRvAdapter(Context context, List originDatas,
int headerLayoutId)
// ItemHeader表示header的数据类型,Content表示内部数据的数据类型
// 初始化,添加header 和 content的布局文件
adapter = new SectionRvAdapter(
this,
contents,
R.layout.item_header_header,
R.layout.item_header_content) {
@Override
protected void onBindItemHeader(BaseViewHolder holder, ItemHeader data, int pos, int type) {
holder.setText(R.id.info1, data.getItemHeaderTitle());
}
@Override
protected void onBindContent(BaseViewHolder holder, Content data, int pos, int type) {
holder.setText(R.id.tv, String.valueOf(data.contentIndex));
}
};
// 添加ISectionRule
adapter.addItemHeaderRule(new ISectionRule() {
@Override
public ItemHeader buildItemHeader(int currentPos, Content preData, Content currentData, Content nextData) {
// 生成header数据
return new ItemHeader("create new header " + currentData.contentIndex);
}
@Override
public boolean isNeedItemHeader(int currentPos, Content preData, Content currentData, Content nextData) {
// 什么时候创建header(当是第一个数据或者index是7的倍数时,插入一个header)
return currentPos == 0 || currentData.contentIndex % 7 == 1;
}
});
mRv.setAdapter(adapter);
一个 ItemHeader 下有多个 Content,类似Map
的数据结构,可以选择在外面构造好数据来进行数据适配
HashMap是无序的,为了保证数据的有序性,使用LinkedHashMap
同样的也提供了两种构造方法
// 直接配置 item header 和 content 的 layout 资源
public SectionRvAdapter(Context context,
LinkedHashMap> originDatas,
int headerLayoutId, int contentLayoutId)
// 只添加 header 的 layout 资源,content的资源可以使用addType方法添加
public SectionRvAdapter(Context context,
LinkedHashMap> originDatas,
int headerLayoutId)
final LinkedHashMap> map = new LinkedHashMap<>();
adapter = new SectionRvAdapter(this, map,
R.layout.item_header_header,
R.layout.item_header_content) {
@Override
protected void onBindItemHeader(BaseViewHolder holder, ItemHeader data, int pos, int type) {
holder.setText(R.id.info1, data.getItemHeaderTitle());
}
@Override
protected void onBindContent(BaseViewHolder holder, Content data, int pos, int type) {
TextView tv = (TextView) holder.getView(R.id.tv);
}
};
支持单击、双击和长按事件
public interface OnItemListener<D> {
// 单击事件
void onClick(int pos, BaseViewHolder holder, D data);
// 长按事件
void onLongPress(int pos, BaseViewHolder holder, D data);
// 双击事件
void onDoubleClick(int pos, BaseViewHolder holder, D data);
}
抽象类的实现,可以选择性的实现需要的方法
public abstract class SimpleItemListener<D> implements OnItemListener<D> {
@Override
public void onClick(int pos, BaseViewHolder holder, D data) {
}
@Override
public void onLongPress(int pos, BaseViewHolder holder, D data) {
}
@Override
public void onDoubleClick(int pos, BaseViewHolder holder, D data) {
}
}
adapter.setItemListener(new SimpleItemListener () {
@Override
public void onClick(int pos, BaseViewHolder holder, GuideData data) {
Toast.makeText(mContext, "单击事件", Toast.LENGTH_SHORT).show();
}
@Override
public void onLongPress(int pos, BaseViewHolder holder, GuideData data) {
Toast.makeText(mContext, "长按事件", Toast.LENGTH_SHORT).show();
}
@Override
public void onDoubleClick(int pos, BaseViewHolder holder, GuideData data) {
Toast.makeText(mContext,"双击事件", Toast.LENGTH_SHORT).show();
}
});
adapter.setItemListener(new SimpleItemListener() {
@Override
public void onClick(int pos, BaseViewHolder holder, ItemModel data) {
// 当是Content数据类型
if (data.getRvType() == AbsAdapter.TYPE_ITEM_DEFAULT) {
Content content = (Content) data.get();
Toast.makeText(SectionAdapterTest.this, content.contentTitle, Toast.LENGTH_SHORT).show();
}else{
// 当是ItemHeader数据类型
}
}
});
为了简化数据更新的方法,内置了数据更新的部分方法
// 插入一条数据
public void insert(int pos, D data)
// 更新数据,isUpdate为false时只会添加数据不会更新显示
public void notifyDataSetChanged(List data, boolean isUpdate)
// 简化分页加载的更新,调用该方法实现增量更新,不会全部刷新,isAllData为true时表示data是全部数据,为false时表示是追加的数据
public void appendTailRangeData(List data, boolean isAllData)
// SectionRvAdapter比较特别,需要使用单独的更新方法
// 使用SectionRule配置数据时,使用此方法更新
public void updateDataAndItemHeader(List data)
// 使用Map配置数据时,使用此方法更新
public void updateDataAndItemHeader(Map> map)
// 分页加载更新数据时调用,仅支持使用SectionRule配置数据
public void appendSectionTailRangeData(List data)
使用Module配置附加功能,目前有HFModule(添加Header和Footer)、LoadMoreModule(预加载更多)
// 生成和添加module
HFModule hfModule = new HFModule(mContext,
R.layout.header_footer_headerly,
R.layout.header_footer_footerly, mRv);
adapter.addHFModule(hfModule);
// 更改Header 和 Footer的数据,类似数据的配置,你可以在实现的方法里绑定数据和监听事件
adapter = new SimpleRvAdapter(mContext, hfModels, R.layout.header_footer_item) {
@Override
public void onBindHeader(BaseViewHolder header) {
super.onBindHeader(header);
}
@Override
public void onBindFooter(BaseViewHolder footer) {
super.onBindFooter(footer);
}
};
// 当只想添加Header或Footer时,使用常亮HFModule.NO_RES表示没有资源
HFModule hfModule = new HFModule(mContext,HFModule.NO_RES,
HFModule.NO_RES, mRv);
// 隐藏Header 和 Footer
public void setFooterEnable(boolean footerEnable)
public void setHeaderEnable(boolean headerEnable)
new LoadMoreModule(int preLoadNum, OnLoadMoreListener lis)
,preLoadNum表示提前几个Item进行预加载,preLoadNum越大预加载的越提前
加载数据完成之后需要调用mLoadMoreModule.finishLoad();
结束本次加载,保证下次加载可以生效
// 触发之后1500秒后加载数据
LoadMoreModule loadMoreM = new LoadMoreModule(4, new OnLoadMoreListener() {
@Override
public void onLoadMore(final LoadMoreModule mLoadMoreModule) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
List tempData = new ArrayList();
for (int i = 0; i < 9; i++) {
tempData.add(new LoadMoreModel("new is " + i));
}
adapter.appendTailRangeData(tempData, false);
mLoadMoreModule.finishLoad();
}
}, 1500);
}
});
adapter.addLoadMoreModule(loadMoreM);
为了区分不同的适配器,生成了adapterId,用来检测当前RecyclerView使用的是不是这个adapter
public boolean isThisAdapter(RecyclerView rv)
//内部类实现
quickAdapter = new TypeRvAdapter(self, demos) {
@Override
public void onBindView(RvViewHolder holder, Demo data, int pos, int type) {
// 给控件绑定数据,必须实现
}
@Override
public void onBindHeader(RvViewHolder header) {
//给Header绑定数据和事件,不需要可以不实现
}
@Override
public void onBindFooter(RvViewHolder footer) {
//给footer绑定数据和事件,不需要可以不实现
}
};
//继承实现
public class MyAdapter extends TypeRvAdapter<Demo> {
public MyAdapter(Context context, List data) {
super(context, data);
}
@Override
public void onBindView(RvViewHolder holder, Demo data, int pos, int type) {
// 给控件绑定数据,必须实现
}
@Override
public void onBindHeader(RvViewHolder header) {
//给Header绑定数据和事件,不需要可以不实现
}
@Override
public void onBindFooter(RvViewHolder footer) {
//给footer绑定数据和事件,不需要可以不实现
}
}