PullToReFresh 实现 RecycleView 横向滑动的刷新和加载更多
2016-08-09 18:10
645 查看
项目地址:https://github.com/moscoper/PullToRefresh.git
前言
一般的刷新和加载更多的效果都是竖直方向的(下拉刷新和上拉加载更多),本篇文章就利用 PullToReFresh 和 RecycleView 来实现水平方向的刷新和加载更多的效果。我们暂且叫它 PullToReshHorizontalRecycleView。PullToReshHorizontalRecycleView
我们在 PullToRefresh 的扩展 这篇文章中介绍过如何利用 PullToReFresh 对其他可以滑动的控件添加下拉和上拉的效果。PullToReshHorizontalRecycleView 的实现和其类似。继承 PullToRefreshBase
新建类PullToReshHorizontalRecycleView继承
PullToRefreshBase<RecyclerView>。并实现
getPullToRefreshScrollDirection,
createRefreshableView,
isReadyForPullStart和
isReadyForPullEnd这四个方法。
getPullToRefreshScrollDirection
方法getPullToRefreshScrollDirection的返回值决定了滑动的方向。返回
Orientation.HORIZONTAL时为水平滑动;返回
Orientation.VERTICAL时为竖直滑动。这里我们需要的是水平方向的滑动所以返回
Orientation.HORIZONTAL。
@Override public Orientation getPullToRefreshScrollDirection() { return Orientation.HORIZONTAL; }
createRefreshableView
方法createRefreshableView的返回值是要添加刷新效果的控件,这里我们需要为横向滑动的 RecycleView 添加刷新效果所以就返回横向滑动的 RecycleView。
@Override protected RecyclerView createRefreshableView(Context context, AttributeSet attrs) { RecyclerView recyclerView = new RecyclerView(context,attrs); LinearLayoutManager mannagerTwo = new LinearLayoutManager(context); mannagerTwo.setOrientation(LinearLayoutManager.HORIZONTAL); recyclerView.setLayoutManager(mannagerTwo); return recyclerView; }
isReadyForPullStart
方法isReadyForPullStart返回
true时表示可以开始刷新的效果了;返回
false时表示还不满足可以触发刷新的效果。我们这里触发展示刷新效果的条件是 RecycleView 的第一个 item 的左边缘在屏幕左边缘的右侧。所以
isReadyForPullStart的具体实现可以如下:
@Override protected boolean isReadyForPullStart() { return isFirstItemVisible(); }
private boolean isFirstItemVisible() { final RecyclerView.Adapter adapter = mRefreshableView.getAdapter(); if (null == adapter || adapter.getItemCount() ==0) { if (DEBUG) { Log.d(LOG_TAG, "isFirstItemVisible. Empty View."); } return true; } else { /** * This check should really just be: * mRefreshableView.getFirstVisiblePosition() == 0, but PtRListView * internally use a HeaderView which messes the positions up. For * now we'll just add one to account for it and rely on the inner * condition which checks getTop(). */ if (getFirstVisiblePosition() <= 1) { final View firstVisibleChild = mRefreshableView.getChildAt(0); if (firstVisibleChild != null) { return firstVisibleChild.getLeft() >= mRefreshableView.getLeft(); } } } return false; }
isReadyForPullEnd
方法isReadyForPullEnd返回
true时表示满足触发加载更多效果的条件,否则表示不满足。这里满足触发加载更多效果的条件是 RecycleView 最后一个 item 的右边缘在屏幕右边缘的左边。所以
isReadyForPullEnd的实现如下:
@Override protected boolean isReadyForPullEnd() { return isLastItemVisible(); }
private boolean isLastItemVisible() { final RecyclerView.Adapter adapter = mRefreshableView.getAdapter(); if (null == adapter || adapter.getItemCount()==0) { if (DEBUG) { Log.d(LOG_TAG, "isLastItemVisible. Empty View."); } return true; } else { final int lastItemPosition = adapter.getItemCount() - 1; final int lastVisiblePosition = getLastVisiblePosition(); if (DEBUG) { Log.d(LOG_TAG, "isLastItemVisible. Last Item Position: " + lastItemPosition + " Last Visible Pos: " + lastVisiblePosition); } /** * This check should really just be: lastVisiblePosition == * lastItemPosition, but PtRListView internally uses a FooterView * which messes the positions up. For me we'll just subtract one to * account for it and rely on the inner condition which checks * getBottom(). */ if (lastVisiblePosition >= lastItemPosition - 1) { final int childIndex = lastVisiblePosition - getFirstVisiblePosition(); final View lastVisibleChild = mRefreshableView.getChildAt(childIndex); if (lastVisibleChild != null) { return lastVisibleChild.getRight() <= mRefreshableView.getRight(); } } } return false; }
完整代码
public class PullRefreshRecyclerView extends PullToRefreshBase<RecyclerView> {
public PullRefreshRecyclerView(Context context, Mode mode) {
super(context, mode);
}
public PullRefreshRecyclerView(Context context) {
super(context);
}
public PullRefreshRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PullRefreshRecyclerView(Context context, Mode mode, AnimationStyle animStyle) {
super(context, mode, animStyle);
}
@Override public Orientation getPullToRefreshScrollDirection() { return Orientation.HORIZONTAL; }
@Override protected RecyclerView createRefreshableView(Context context, AttributeSet attrs) {
RecyclerView recyclerView = new RecyclerView(context,attrs);
LinearLayoutManager mannagerTwo = new LinearLayoutManager(context);
mannagerTwo.setOrientation(LinearLayoutManager.HORIZONTAL);
//recyclerView.addItemDecoration(
// new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL_LIST));
recyclerView.setLayoutManager(mannagerTwo);
return recyclerView;
}
public void addItemDecoration(RecyclerView.ItemDecoration itemDecoration){
mRefreshableView.addItemDecoration(itemDecoration);
}
public void setAdapter(RecyclerView.Adapter adapter){
mRefreshableView.setAdapter(adapter);
}
@Override protected boolean isReadyForPullEnd() { return isLastItemVisible(); }
@Override protected boolean isReadyForPullStart() { return isFirstItemVisible(); }
private boolean isLastItemVisible() { final RecyclerView.Adapter adapter = mRefreshableView.getAdapter(); if (null == adapter || adapter.getItemCount()==0) { if (DEBUG) { Log.d(LOG_TAG, "isLastItemVisible. Empty View."); } return true; } else { final int lastItemPosition = adapter.getItemCount() - 1; final int lastVisiblePosition = getLastVisiblePosition(); if (DEBUG) { Log.d(LOG_TAG, "isLastItemVisible. Last Item Position: " + lastItemPosition + " Last Visible Pos: " + lastVisiblePosition); } /** * This check should really just be: lastVisiblePosition == * lastItemPosition, but PtRListView internally uses a FooterView * which messes the positions up. For me we'll just subtract one to * account for it and rely on the inner condition which checks * getBottom(). */ if (lastVisiblePosition >= lastItemPosition - 1) { final int childIndex = lastVisiblePosition - getFirstVisiblePosition(); final View lastVisibleChild = mRefreshableView.getChildAt(childIndex); if (lastVisibleChild != null) { return lastVisibleChild.getRight() <= mRefreshableView.getRight(); } } } return false; }
private int getFirstVisiblePosition(){
int position = 0;
RecyclerView.LayoutManager manager = mRefreshableView.getLayoutManager();
if (manager instanceof LinearLayoutManager){
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) manager;
return linearLayoutManager.findFirstVisibleItemPosition();
}
return position;
}
private int getLastVisiblePosition(){
int position = 0;
RecyclerView.LayoutManager manager = mRefreshableView.getLayoutManager();
if (manager instanceof LinearLayoutManager){
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) manager;
return linearLayoutManager.findLastVisibleItemPosition();
}
return position;
}
private boolean isFirstItemVisible() { final RecyclerView.Adapter adapter = mRefreshableView.getAdapter(); if (null == adapter || adapter.getItemCount() ==0) { if (DEBUG) { Log.d(LOG_TAG, "isFirstItemVisible. Empty View."); } return true; } else { /** * This check should really just be: * mRefreshableView.getFirstVisiblePosition() == 0, but PtRListView * internally use a HeaderView which messes the positions up. For * now we'll just add one to account for it and rely on the inner * condition which checks getTop(). */ if (getFirstVisiblePosition() <= 1) { final View firstVisibleChild = mRefreshableView.getChildAt(0); if (firstVisibleChild != null) { return firstVisibleChild.getLeft() >= mRefreshableView.getLeft(); } } } return false; }
}
结语
PullToReshHorizontalRecycleView 的用法和原有的 PullToReFresh 的控件是一样的,这里不再赘述。相关文章推荐
- pulltorefresh+recycleview 实现的瀑布流(带下拉刷新,上拉加载更多)
- PullToRefresh实现ListView的刷新,加载更多的展示
- 使用PullToRefreshScrollView实现无线轮播和ListView同时刷新加载
- 将上拉加载更多下拉刷新PullToRefreshView用到项目中去
- 针对自定义组件上拉刷新下拉加载更多PullToRefreshView的分析(一)
- 针对自定义组件上拉刷新下拉加载更多PullToRefreshView的分析(二)
- pulltorefreshscrollview的简单实现(上拉刷新,下拉加载)
- pulltorefresh上拉加载,没有更多数据的时候显示“加载完成”,不回调刷新接口的实现
- 针对自定义组件上拉刷新下拉加载更多PullToRefreshView的分析(一)
- TabLayout横向滑动,DrawerLayout侧滑,PullToRefreshListView上拉刷新下拉加载联用
- pulltorefresh(一)使用介绍,实现下拉刷新上拉加载更多
- 【Android开发笔记】pulltorefresh实现下拉刷新和上拉加载更多
- pulltorefresh(一)使用介绍,实现下拉刷新上拉加载更多
- pulltoRefreshSwipeMenuListview-带侧滑的可下拉刷新、上拉加载更多的控件
- [置顶] Android-PullToRefresh上拉下拉刷新加载更多,以及gridview刷新功能的Library下载地址
- PullToRefresh实现listview刷新加载
- PullToRefresh实现listview刷新加载
- 使用Android开源工具PullToRefresh实现上啦刷新下拉加载
- 《android》下拉刷新上拉加载更多控件 PullToRefreshView
- android使用PullToRefresh实现上拉加载和下拉刷新效果