您的位置:首页 > 其它

SwipeRefreshLayout+RecyclerView 实现上拉追加功能

2016-03-09 18:13 369 查看
参考连接1:http://blog.csdn.net/bboyfeiyu/article/details/39935329

直奔主题,按照上面参考链接确实是满足需求,但RecyclerView作为一个比ListView更灵活的一个控件,完全取代ListView只是时间的问题。所以这篇博文是记录我自己的实现方法。

首先是RecyclerView增加上拉的时候 加载中的view动画,可以沿用上面参考链接的listview_footer.xml

在ListView中 我们可以用addHeaderView或者addFooterView添加头尾,但RecyclerView并没有这个功能,网上参考是改写RecyclerViewAdapter

public class RecyclerViewAdapter extends RecyclerView.Adapter<ViewHolder> {

private static final int TYPE_ITEM = 0;
private static final int TYPE_FOOTER = 1;
private Context mContext;
private List<listItemBean> mItemsList;

public RecyclerViewAdapter(Context context, List<listItemBean> itemsList) {
mContext=context;
mItemsList = itemsList;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_list_item,parent,false);
return new ItemViewHolder(view);
} else if (viewType == TYPE_FOOTER) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_footer,parent,false);
view.setVisibility(View.GONE);
return new FooterViewHolder(view);
}
return null;
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (holder instanceof ItemViewHolder) {
listItemBean itemBean = mItemsList.get(position);
((ItemViewHolder)holder).mDetailTextView.setText(itemBean.getDetailText());
((ItemViewHolder)holder).mMainTextView.setText(itemBean.getMainText());
}
}

@Override
public int getItemCount() {
return mItemsList.size()+1;
//return mItemsList.size();
}

@Override
public int getItemViewType(int position) {
if (position+1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}

class ItemViewHolder extends RecyclerView.ViewHolder {
public final TextView mMainTextView;
public final TextView mDetailTextView;
public ItemViewHolder(View itemView) {
super(itemView);
mMainTextView = (TextView) itemView.findViewById(R.id.tv_main);
mDetailTextView= (TextView) itemView.findViewById(R.id.tv_detail);
}
}

class FooterViewHolder extends RecyclerView.ViewHolder{
public final ProgressBar progressBar;
public final TextView loadingTips;
public FooterViewHolder(View view) {
super(view);
progressBar = (ProgressBar) view.findViewById(R.id.pull_to_refresh_load_progress);
loadingTips = (TextView) view.findViewById(R.id.pull_to_refresh_loading_text);
}
}
}


在返回FooterViewHolder的时候,有一句view.setVisibility(View.GONE); 稍候解释为什么怎么做。

在getItemCount()+1是为了FooterViewHolder预留一个view的位置,到此RecyclerView的改写基本完成,往下就是重点了

/////////////////////////////////////////喝口茶的分割线/////////////////////////////////////////

RefreshLayout中,首先肯定是要把getChildView的ListView改成RecyclerView,其中也要替换onScrolled的监听吧。这些就不详细论述了,直接上改变后的代码

private void getChildView() {
int childs = getChildCount();
if (childs > 0) {
View childView = getChildAt(0);
if (childView instanceof RecyclerView) {
mRecyclerView = (RecyclerView) childView;
// 设置滚动监听器给RecyclerView, 使得滚动的情况下也可以自动加载
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
// 滚动时到了最底部也可以加载更多
if (canLoad()) {
loadData();
}
}

@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
});
Log.d(TAG, "### 找到RecyclerView");
}
}
}


第二个变化点,判断是否到了最底部函数isBottom;其中我们必须知道RecyclerView是有横 纵 瀑布等LayoutManager的,我们要恰当的分开处理。

/*判断是否到了最底部*/
private boolean isBottom() {
RecyclerView.LayoutManager layoutManager = null;
if (mRecyclerView != null) {
layoutManager = mRecyclerView.getLayoutManager();
}else{
return false;
}

if(layoutManager instanceof LinearLayoutManager){
LinearLayoutManager lm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
int position = lm.findLastVisibleItemPosition();
int itemCount = lm.getItemCount();
Log.d(TAG,"current position:"+position);
Log.d(TAG,"itemCount:"+itemCount);
if(position+1 == lm.getItemCount()
&& lm.findViewByPosition(position).getBottom() <= getHeight()){
Log.d(TAG, "RefreshLayout 滑动到底部了");
return true;
}
}else if(layoutManager instanceof StaggeredGridLayoutManager){
// http://www.imooc.com/qadetail/91200 Log.d(TAG, "layoutManager instanceof StaggeredGridLayoutManager not yet implemented");
Log.d(TAG, "RefreshLayout 滑动到底部了");
}
return false;
}


好了,离完工就差最后一步了,就是setLoading(true/false),我觉得参考链接的博主暴露这个接口真的设计得非常好,完全和原生的swipeRefreshLayout下拉刷新媲美。

也是废话不说,上更改后的代码

public void setLoading(boolean loading) {
isLoading = loading;
LinearLayoutManager lm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
int position = lm.findLastVisibleItemPosition();
//        int itemCount = mRecyclerView.getLayoutManager().getItemCount();
//        int childCount = mRecyclerView.getLayoutManager().getChildCount();
//        Log.d(TAG,"getChildCount:"+childCount);
//        Log.d(TAG,"getItemCount:"+itemCount);
View lastView = lm.findViewByPosition(position);
if (isLoading) {
lastView.setVisibility(View.VISIBLE);
} else {
lastView.setVisibility(View.GONE);
mDownY = 0;
mLastY = 0;
}
}


来到这里大家应该都明白了之前,在onCreateViewHolder返回FooterViewHolder的时候,有一句view.setVisibility(View.GONE)吧,其实那个加载动画一直都在整个RecyclerView的底部,我只是在恰当的时间隐藏/展示它罢了。

但这里大家必须注意的就是,此时的RecyclerView的itemsize永远是比你实际数据多1的,这点请大家注意!!!重要的话只说一遍。

至于demo,基本上可参照原参考链接的,这里也分享一下近日自己做的一个记账app,简单粗暴。
https://github.com/MrZhaozhirong/MyBill
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: