您的位置:首页 > 移动开发 > Android开发

Android LRecyclerView实现下拉刷新,滑动到底部自动加载更多

2017-12-22 10:17 1211 查看
随着功能的不断优化,框架中的类或者接口名字会有变动,为了获取准确的使用方法,请参考最新的说明文档:点此查看

简介

LRecyclerView是支持addHeaderView、 addFooterView、下拉刷新、分页加载数据的RecyclerView。

它对 RecyclerView 控件进行了拓展,给RecyclerView增加HeaderView、FooterView,并且不需要对你的Adapter做任何修改。

主要功能

下拉刷新、滑动到底部自动加载下页数据;

可以方便添加Header和Footer;

头部下拉样式可以自定义;

具备item点击和长按事件。

网络错误加载失败点击Footer重新请求数据;

可以动态为FooterView赋予不同状态(加载中、加载失败、滑到最底等)。

项目地址:https://github.com/jdsjlzx/LRecyclerView

效果图



Gradle

Step 1. 在你的根build.gradle文件中增加JitPack仓库依赖。

allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
1
2
3
4
5
6
[/code]

Step 2. 在你的model的build.gradle文件中增加LRecyclerView依赖。

compile 'com.github.jdsjlzx:LRecyclerView:1.2.9'
1
[/code]

使用

填充数据

mDataAdapter = new DataAdapter(this);
mDataAdapter.setData(dataList);

mLRecyclerViewAdapter = new LRecyclerViewAdapter(this, mDataAdapter);
mRecyclerView.setAdapter(mLRecyclerViewAdapter);
1
2
3
4
5
[/code]

DataAdapter是用户自己真正的adapter,用户自己定义;

LRecyclerViewAdapter提供了一些实用的功能,使用者不用关心它的实现,只需构造的时候把自己的mDataAdapter以参数形式传进去即可。

详细使用可以参加demo。

添加HeaderView、FooterView

//add a HeaderView
RecyclerViewUtils.setHeaderView(mRecyclerView, new SampleHeader(this));

//add a FooterView
RecyclerViewUtils.setFooterView(mRecyclerView, new SampleFooter(this));
1
2
3
4
5
6
[/code]

下拉刷新和加载更多

为了大家使用方便,将需要用的方法统一封装到接口LScrollListener中。

mRecyclerView.setLScrollListener(new LRecyclerView.LScrollListener() {

@Override
public void onScrollUp() {
}

@Override
public void onScrollDown() {
}

@Override
public void onScrolled(int distanceX, int distanceY) {
}

@Override
public void onScrollStateChanged(int state) {

}

});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[/code]

LScrollListener实现了onScrollUp()、onScrollDown()、onScrolled、onScrollStateChanged四个事件,如下所示:

void onScrollUp();//scroll down to up

void onScrollDown();//scroll from up to down

void onScrolled(int distanceX, int distanceY);// moving state,you can get the move distance

void onScrollStateChanged(int state);
1
2
3
4
5
6
7
8
[/code]

onScrollUp()——RecyclerView向上滑动的监听事件;

onScrollDown()——RecyclerView向下滑动的监听事件;

onScrollDown()——RecyclerView正在滚动的监听事件;

onScrollStateChanged——RecyclerView滑动到状态监听;

加载更多(加载下页数据)

mRecyclerView.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore() {

}
});
1
2
3
4
5
6
[/code]



下拉刷新

为了达到和Listview的下拉刷新效果,本项目没有借助SwipeRefreshLayout控件,而是在自定义RecyclerView头部实现的刷新效果。

mRecyclerView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {

}
});
1
2
3
4
5
6
[/code]

这里的下拉刷新效果借鉴了开源库:AVLoadingIndicatorView

设置加载样式:

mRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader);
mRecyclerView.setArrowImageView(R.drawable.iconfont_downgrey);
1
2
[/code]

AVLoadingIndicatorView库有多少效果,LRecyclerView就支持多少下拉刷新效果,当然你也可以自定义下拉效果。

效果图:



下拉刷新逻辑处理:

从上面的LScrollListener介绍中就可以看出,实现下拉刷新只要在onRefresh()接口中处理即可。

强制刷新

根据大家的反馈,增加了一个强制刷新的方法,使用如下:

mRecyclerView.forceToRefresh();
1
[/code]

无论是下拉刷新还是强制刷新,刷新完成后调用下面代码:

mRecyclerView.refreshComplete();
mLRecyclerViewAdapter.notifyDataSetChanged();
1
2
[/code]

加载网络异常处理

加载数据时如果网络异常或者断网,LRecyclerView为你提供了重新加载的机制。

效果图:



网络异常出错代码处理如下:

RecyclerViewStateUtils.setFooterViewState(getActivity(), mRecyclerView, getPageSize(), LoadingFooter.State.NetWorkError, mFooterClick);

private View.OnClickListener mFooterClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
RecyclerViewStateUtils.setFooterViewState(getActivity(), mRecyclerView, getPageSize(), LoadingFooter.State.Loading, null);
requestData();
}
};
1
2
3
4
5
6
7
8
9
[/code]

上面的mFooterClick就是我们点击底部的Footer时的逻辑处理事件,很显然我们还是在这里做重新请求数据操作。

点击事件和长按事件处理

在Hongyang前辈的博客中有下描述:

Click and LongClick

不过一个挺郁闷的地方就是,系统没有提供ClickListener和LongClickListener。

不过我们也可以自己去添加,只是会多了些代码而已。

实现的方式比较多,你可以通过mRecyclerView.addOnItemTouchListener去监听然后去判断手势, 当然你也可以通过adapter中自己去提供回调,这里我们选择后者,前者的方式,大家有兴趣自己去实现。

出自:http://blog.csdn.net/lmj623565791/article/details/45059587

Hongyang大神选择了后者,LRecyclerView早期选择了前者,经过实践总结,在adapter中实现点击事件会好点。

先看下怎么使用:

mLRecyclerViewAdapter.setOnItemClickLitener(new OnItemClickLitener() {
@Override
public void onItemClick(View view, int position) {

}

@Override
public void onItemLongClick(View view, int position) {

}
});
1
2
3
4
5
6
7
8
9
10
11
[/code]

原理就是实现viewHolder.itemView的点击和长按事件。由于代码过多就不贴出来了。

viewHolder.itemView是RecyclerView.Adapter中本身就具有的,不用额外定义。

源码如下:

public static abstract class ViewHolder {
public final View itemView;
int mPosition = NO_POSITION;
int mOldPosition = NO_POSITION;
long mItemId = NO_ID;
int mItemViewType = INVALID_TYPE;
int mPreLayoutPosition = NO_POSITION;
1
2
3
4
5
6
7
[/code]

设置空白View(setEmptyView)

mRecyclerView.setEmptyView(view);
1
[/code]

注意布局文件:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<com.github.jdsjlzx.recyclerview.LRecyclerView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>

<include
android:id="@+id/empty_view"
layout="@layout/layout_empty"
android:visibility="gone"/>
</RelativeLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[/code]

分享

介绍完了LRecyclerView,似乎还少些什么,对了,那就是adapter了。

为了方便大家使用,分享个封装过的adapter。

public class ListBaseAdapter<T extends Entity> extends RecyclerView.Adapter {
protected Context mContext;
protected int mScreenWidth;

public void setScreenWidth(int width) {
mScreenWidth = width;
}

protected ArrayList<T> mDataList = new ArrayList<>();

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

}

@Override
public int getItemCount() {
return mDataList.size();
}

public List<T> getDataList() {
return mDataList;
}

public void setDataList(Collection<T> list) {
this.mDataList.clear();
this.mDataList.addAll(list);
notifyDataSetChanged();
}

public void addAll(Collection<T> list) {
int lastIndex = this.mDataList.size();
if (this.mDataList.addAll(list)) {
notifyItemRangeInserted(lastIndex, list.size());
}
}

public void clear() {
mDataList.clear();
notifyDataSetChanged();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[/code]

ListBaseAdapter使用了泛型,简单方便,消除了强制类型转换。

使用如下:

private class DataAdapter extends ListBaseAdapter<ItemModel>{

private LayoutInflater mLayoutInflater;

public DataAdapter(Context context) {
mLayoutInflater = LayoutInflater.from(context);
mContext = context;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(mLayoutInflater.inflate(R.layout.sample_item_text, parent, false));
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ItemModel item = mDataList.get(position);

ViewHolder viewHolder = (ViewHolder) holder;
viewHolder.textView.setText(item.title);
}

private class ViewHolder extends RecyclerView.ViewHolder {

private TextView textView;

public ViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.info_text);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[/code]

ListBaseAdapter虽然功能不强大,但是使用很方便。

结语

LRecyclerView使用方便简单,无论你添加多少Header和Footer,你都不用担心position的问题,除了方便还是方便。

最后再介绍下项目地址:https://github.com/jdsjlzx/LRecyclerView

如果觉得上面的例子UI简单,这里再分享个公司项目:https://github.com/jdsjlzx/Community

效果图:



如果大家使用过程中有任何问题,请留言,我会及时修正。

注意:最近有同学想SwipeRefreshLayout结合LRecyclerView使用,会有冲突,为了大家使用方便,特别增加了LuRecyclerView类,具体参见SwipeRefreshLayoutActivity类的实现。

后记:如果后续再增加功能,请详细看github上面的项目介绍,将不在博客里面更新。

最后更新日期:2016.08.07

小功能分享

1.一键置顶

@Override
public void onScrolled(int distanceX, int distanceY) {

if (null != headerView) {
if (distanceY == 0 || distanceY < headerView.getHeight()) {
toTopBtn.setVisibility(View.GONE);
}
} else {
if (distanceY == 0) {
toTopBtn.setVisibility(View.GONE);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
[/code]

toTopBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRecyclerView.scrollToPosition(0);
toTopBtn.setVisibility(View.GONE);
}
});
1
2
3
4
5
6
7
[/code]

</script>


转自:http://blog.csdn.net/jdsjlzx/article/details/51794220
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐