Google官方出的SwipeRefreshLayout还挺好的,不过只能支持刷新,加载的话需要稍加代码改动。那么既然要改我们不如直接SwipeRefreshLayout+RecyclerView封装下,目前最流行的RecyclerView列表式控件,它能实现网格状,竖向,横向和各种布局样式,listView的时代已经过去了。
下面我们简单说下思路:
1、SwipeRefreshLayout大家可以看看源码,我也不会太解析源码,以免越说越乱就跳过这个步骤了,我们可以仿照着官方api自顶一个SwipeRefreshLayout,大致思路就是我们可以在SwipeRefreshLayout的子布局的childAt(0)的位置就是第一个位置,塞进一个头布局,可以自定义,然后检测屏幕手势滑动,当子布局滑到顶部,启动头布局,给头布局添加动画和不同的状态
2、再上面的SwipeRefreshLayout的基础上,我们添加一个尾布局,当滑动到底部的时候我们启动尾布局,当滑动距离超过尾布局高度时启动加载功能,
3、我们给第二步中的添加子布局RecyclerView,顺便说下,因为可能存在刷新失败的情况,大家可以同时添加一个自定义的额emptyLayout用来显示加载失败,没有内容,没有网络等情况。
下面直接上个demo;demo里面封装包括:
1、emptyLayout 用来显示加载成功失败,或空白的情况
2、recyclerView的baseAdapter
3、给recyclerView添加自定义分割线
4、swipeRefreshLayout刷新时添加自定义头部布局,可以自行更改
5、swipeRefreshLayout上拉加载时添加尾部布局
6、自定义LayoutManager
7、recyclerView原生侧滑删除等
8、SharedPreferencesHelper封装DateUtil工具类封装
侧滑删除使用方式,这里不是侧滑显示按钮点击删除,是使用远程的recyclerview的侧滑:
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(customNotificationAdapter);
ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
自定义刷新加载控件引用方式:
在activity或fragment中这样初始化:
SwipeRecyclerView refreshLayout = (SwipeRecyclerView) findViewById(R.id.refreshLayout);
refreshLayout.setRefreshDateTag(this.getClass().getSimpleName());//用来控制刷新时间的tag
recyclerView = refreshLayout.getRecyclerView();
for(int i =0;i<20;i++){
list.add("这是第"+i+"条数据");
}
MyLayoutManager myLayoutManager = new MyLayoutManager(this);
recyclerView.setLayoutManager(myLayoutManager);//控制recyclerView布局管理器即水平还是网格还是竖直
recyclerView.addItemDecoration(new RecycleViewDivider(this, LinearLayoutManager.HORIZONTAL, 1,
ContextCompat.getColor(this,R.color.h_line_color)));//设置分割线
informAdapter = new InformAdapter(this,list);
recyclerView.setAdapter(informAdapter);
swipeRecyclerView.setOnSwipeRecyclerViewListener(this);
如果想禁止刷新或加载可以这样设置:
swipeRecyclerView.setCanLoadMore(false);
swipeRecyclerView.setCanLoadMore(false);
停止刷新调用:
refreshLayout.onRefreshFinish();
停止加载调用
refreshLayout.onLoadFinish();
当列表中没有数据时我们可以这样设置
refreshLayout.setRecyclerViewVisibility(EmptyLayout.NODATA);
当列表加载错误时
refreshLayout.setRecyclerViewVisibility(EmptyLayout.LOADING_ERROR);
注意这一行代码
refreshLayout.setRefreshDateTag(this.getClass().getSimpleName());//用来控制刷新时间的tag
这个设置是为了区别你在哪个页面应用了自定义控件添加tag值,因为我们得刷新时间是利用shareprefrence保存至本地的,我们需要区别每个不同的页面显示该页面对应的刷新时间不然会每个页面的刷新时间都是一样的,贼尴尬。
另外因为我们外部使用swipeRefreshLayout内部使用recyclerView,这两个控件会有滑动冲突,即可能出现没滑到列表顶部但启动花心了:冲突解决方案:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int topRowVerticalPosition =
(recyclerView == null || recyclerView.getChildCount() == 0) ? 0 : recyclerView.getChildAt(0).getTop();
swipeRefreshLayout.setEnabled(topRowVerticalPosition >= 0);
// swipeRefreshLayout.setEnabled(false);
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
});
同样利用不同的emptyType值来判断显示recyclerView还是emptyLayout,是刷新还是加载还是网络错误,可以再行在EmptyLayout中添加对应的emptyType的值,
public void setRecyclerViewVisibility(int emptyType) {
if (emptyLayout == null || recyclerView == null) return;
emptyLayout.setErrorType(emptyType);
switch (emptyType) {
case EmptyLayout.LOADING_ERROR:
recyclerView.setVisibility(View.GONE);
onRefreshFinish();
onLoadFinish();
break;
case EmptyLayout.NETWORK_LOADING:
emptyLayout.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
break;
case EmptyLayout.NETWORK_LOADING_RERESH://刷新
emptyLayout.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
break;
case EmptyLayout.NETWORK_LOADING_LOADMORE://加载
emptyLayout.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
break;
case EmptyLayout.NODATA:
onRefreshFinish();
onLoadFinish();
recyclerView.setVisibility(View.GONE);
break;
case EmptyLayout.HIDE_LAYOUT:
onRefreshFinish();
onLoadFinish();
emptyLayout.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
break;
}
}
注意:
baseAdapter的头布局没有点击时间,如果需要请自行添加。
如果想修改刷新的头布局的话可以修改pull_to_refresh_header_vertical.xml然后在
SwipeRecyclerView类中修改相关heandview代码