对RecyclerView的一个封装,添加一些实用的功能
项目地址
效果图与示例APK
主要功能:
- 下拉刷新,使用默认的下拉刷新控件
- 页面加载数据过程中显示LoadingView
- 页面加载数据出错时显示ErrorView
- 页面数据大小为0时显示EmptyView
- 自动加载,当页面到底部或者当前页面显示不全时,自动加载其余数据,并显示LoadMoreView
- 加载更多时出错自动停止加载更多,并显示LoadMoreFailedView
- 没有更多数据加载时,显示NoMoreView
- 支持Header View和Footer View
- 除下拉刷新以外,其余View均可自定义
- 支持多种Item类型布局
- 支持GridLayout和瀑布流
使用方式:
1.添加Gradle依赖
dependencies{
compile 'compile 'zlc.season:practicalrecyclerview:1.0.2'
}
复制代码
2.在布局文件中添加PracticalRecyclerView
<zlc.season.practicalrecyclerview.PracticalRecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:loading_layout="@layout/default_loading_layout" //可以自定义,也可以不设置使用默认的布局
app:empty_layout="@layout/default_empty_layout" //以下属性同样不设置即为使用默认的布局
app:error_layout="@layout/default_error_layout"
app:load_more_layout="@layout/default_load_more_layout"
app:no_more_layout="@layout/default_no_more_layout"
app:load_more_failed_layout="@layout/default_load_more_failed_layout"/>
复制代码
3.添加代码
首先定义一个POJO类, 并实现ItemType接口:
class NormalBean implements ItemType {
String mImg;
String mTitle;
String mContent;
NormalBean(String img, String title, String content) {
mImg = img;
mContent = content;
mTitle = title;
}
@Override
public int itemType() {
return 0;
}
}
复制代码
这里返回的item type 表示是item的类型, 如果列表只有一种类型的item, 那么返回0就可以了, 如果有多种item, 则对应类型的item返回对应类型的item type. 这里简单的返回0 .
接着定义ViewHolder, 继承自AbstractViewHolder, 并提供泛型参数:
class NormalViewHolder extends AbstractViewHolder<NormalBean> {
@BindView(R.id.head)
ImageView mHead;
@BindView(R.id.title)
TextView mTitle;
@BindView(R.id.content)
TextView mContent;
private Context mContext;
NormalViewHolder(ViewGroup parent) {
super(parent, R.layout.normal_item); //与对应的item layout进行绑定.
mContext = parent.getContext(); //如果viewholder需要context,在这里获取.
ButterKnife.bind(this, itemView); //这里使用了butterknife进行控件绑定,也可以手写 // itemView.findViewById()来获取对应的控件.
}
@Override
public void setData(NormalBean data) {
Picasso.with(mContext).load(Uri.parse(data.mImg)).into(mHead);
mTitle.setText(data.mTitle);
mContent.setText(data.mContent);
}
}
复制代码
在Viewholder中进行View的创建和绑定, 如果需要绑定按钮的单击事件或者其他的一些事件, 在此处进行再好不过了.
接下来创建Adatper, 继承自AbstractAdapter<T , VH>, 并提供泛型参数:
class SingleItemAdapter extends AbstractAdapter<NormalBean, NormalViewHolder> {
@Override
protected NormalViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
return new NormalViewHolder(parent);
}
@Override
protected void onNewBindViewHolder(NormalViewHolder holder, int position) {
holder.setData(get(position));
}
}
复制代码
adapter 类中非常简洁, 只需要在onNewCreateViewHolder()中创建ViewHolder, 在onNewBindViewHolder()中调用viewholder的setData()即可, 这样adapter和viewholder的逻辑就分离开来,互不干扰.
最后,在Activity或者Fragment中进行最后的配置:
PracticalRecyclerView mRecycler;
private SingleItemAdapter mAdapter = new SingleItemAdapter();
...
mRecycler.setLayoutManager(new LinearLayoutManager(this));
mRecycler.setAdapterWithLoading(mAdapter);
mRecycler.setRefreshListener(new PracticalRecyclerView.OnRefreshListener() {
@Override
public void onRefresh() {
mPresenter.loadData(true);
}
});
mRecycler.setLoadMoreListener(new PracticalRecyclerView.OnLoadMoreListener() {
@Override
public void onLoadMore() {
mPresenter.loadData(false);
}
});
...
//更多详细代码请下载demo查看
复制代码
4.添加Header 和 Footer
要添加Header和Footer, 可以选择实现SectionItem接口, 或者继承SectionItemImpl, 如下所示:
class Header implements SectionItem {
@BindView(R.id.banner_guide_content)
BGABanner mBanner;
@Override
public View createView(ViewGroup parent) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_item, parent, false);
ButterKnife.bind(this, view);
return view;
}
@Override
public void onBind() {
mBanner.setAdapter(new BGABanner.Adapter() {
@Override
public void fillBannerItem(BGABanner banner, View view, Object model, int position) {
((ImageView) view).setImageResource((int) model);
}
});
mBanner.setData(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f,
R.mipmap.g, R.mipmap.h), null);
}
}
复制代码
这里使用了一个开源轮播库BGABanner当作Header, 该库的链接在此: BGAbanner
接着调用Adapter的addHeader() 或者addFooter()方法将该Header或Footer添加到adapter中:
mAdapter.addHeader(new Header());
复制代码
5.Configure 接口和ConfigureAdapter类
当默认的属性不能满足需求时, 可以自定义layout 并设置为PracticalRecyclerView的属性:
...
app:load_more_failed_layout="@layout/custom_load_more_failed_layout" //当加载更多失败时显示的View
...
复制代码
若需要对该View进行设置, 就需要用到Configure接口, Configure接口定义了以下方法,分别对属性中设置的View进行设置:
public interface Configure {
void configureEmptyView(View emptyView); //对Empty View 进行设置
void configureErrorView(View errorView); //对Error View 进行设置
void configureLoadingView(View loadingView); // 对LoadingView 进行设置
void configureLoadMoreView(View loadMoreView); // 对LoadMore View进行设置
void configureNoMoreView(View noMoreView); //对NoMore View进行设置
void configureLoadMoreErrorView(View loadMoreErrorView); // 对LoadMoreError View进行设置
}
复制代码
ConfigureAdapter是对Configure接口的一个包装类, 可以选择实现其中的某一些方法,从而设置对应的View:
mRecycler.configureView(new ConfigureAdapter() {
@Override
public void configureLoadMoreFailedView(View loadMoreFailedView) {
super.configureLoadMoreFailedView(loadMoreFailedView);
loadMoreFailedView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(SingleItemActivity.this, "点击LoadMoreFailedView时应该进行的操作", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void configureErrorView(View errorView) {
super.configureErrorView(errorView);
errorView.dosomething();
}
});
复制代码
6.更多功能将会继续开发和完善
若您对此项目有一些自己的想法 , 欢迎来提Pull Request.