您现在的位置是:首页 > 文章详情

RecyclerView与SwipeRefreshLayout的完美搭配

日期:2016-09-13点击:530
SwipeRefreshLayout 是谷歌公司推出的用于下拉刷新的控件,在Version 19.1之后SwipeRefreshLayout 被放到support v4中。我们在前面也已经说过一个SwipeRefreshLayout和ListView实现上拉加载、下拉刷新的例子。而现在RecyclerView也已作为实现列表功能的首选组件,而它本身并没有实现上拉加载、下拉刷新的功能,本节我们就来利用SwipeRefreshLayout 和RecyclerView来实现上拉加载、下拉刷新的功能。
SwipeRefreshLayout 常用的方法如下:
  • setOnRefreshListener(OnRefreshListener):下拉刷新监听器,当用户下拉的时候会触发
  • setRefreshing(boolean):设置SwipeRefreshLayout当前是否处于刷新状态,一般是在请求数据的时候设置为true,在数据被加载到View中后,设置为false。
  • isRefreshing():检查是否处于刷新状态
  • setColorSchemeResources():设置进度条的颜色主题,最多设置四种,以前的setColorScheme()方法已经弃用了。
  • setProgressViewOffset(boolean scale, int start, int end) 调整进度条距离屏幕顶部的距离
布局文件很简单
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:paddingBottom="@dimen/activity_vertical_margin"  android:paddingLeft="@dimen/activity_horizontal_margin"  android:paddingRight="@dimen/activity_horizontal_margin"  android:paddingTop="@dimen/activity_vertical_margin"  tools:context="com.xmr.recycleandswiperefresh.MainActivity">   <android.support.v4.widget.SwipeRefreshLayout  android:id="@+id/srl_main"  android:layout_width="match_parent"  android:layout_height="match_parent">   <android.support.v7.widget.RecyclerView  android:id="@+id/ryv_main"  android:layout_width="match_parent"  android:layout_height="match_parent" />   </android.support.v4.widget.SwipeRefreshLayout> </RelativeLayout> 
接着在Activity中获取SwipeRefreshLayout控件并且设置OnRefreshListener监听器,同时实现里边的onRefresh()方法,在该方法中进行网络请求最新数据,然后刷新RecyclerView列表同时设置SwipeRefreshLayout的显示效果。具体代码如下:
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override  public void onRefresh() { //实际项目中这里一般是用网络请求获取数据  mList.add("下拉刷新");  mAdapter.notifyDataSetChanged();  mSwipeRefreshLayout.setRefreshing(false);  } });
RecyclerView的实现:
第一种,下拉刷新和上拉刷新都用SwipeRefreshLayout 自带的效果
 mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override  public void onScrollStateChanged(RecyclerView recyclerView,  int newState) { super.onScrollStateChanged(recyclerView, newState);  if (newState == RecyclerView.SCROLL_STATE_IDLE  && lastVisibleItem + 1 == mAdapter.getItemCount()) { mSwipeRefreshLayout.setRefreshing(true);  //实际项目中这里一般是用网络请求获取数据  mList.add("上拉加载");  //为了有刷新的效果,延迟关闭刷新效果  mSwipeRefreshLayout.postDelayed(new Runnable() { @Override  public void run() { mSwipeRefreshLayout.setRefreshing(false);  mAdapter.notifyDataSetChanged();   } }, 2000);   } } @Override  public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy);  //判断是当前layoutManager是否为LinearLayoutManager  // 只有LinearLayoutManager才有查找第一个和最后一个可见view位置的方法  if (linearLayoutManager instanceof LinearLayoutManager) { //获取最后一个可见view的位置  lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();  //获取第一个可见view的位置 // int firstItemPosition = linearLayoutManager.findFirstVisibleItemPosition();  } } });
效果如下:


第二种实现下拉刷新用SwipeRefreshLayout 自带的效果, 上拉加载我们可以给RecyclerView 添加一个类似FooterView的item。
我们在Adapter中实现:
package com.xmr.recycleandswiperefresh;  import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView;  import java.util.List;  /**  * Created by Administrator on 2016/9/13.  */ public class RefreshAdapter1 extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context mContext;  private List<String> mDatas;  private static final int TYPE_ITEM = 0; //普通Item View   private static final int TYPE_FOOTER = 1; //底部FootView  //已经到底了  public static final int PULLUP_LOAD_MORE = 0;  //正在加载中  public static final int LOADING_MORE = 1;  //上拉加载状态-默认为0  private int load_more_status = 0;   public RefreshAdapter1(Context mContext, List<String> mDatas) { this.mContext = mContext;  this.mDatas = mDatas;  } @Override  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //进行判断显示类型,来创建返回不同的View  if (viewType == TYPE_ITEM) { View view = LayoutInflater.from(parent.getContext()).inflate( R.layout.item_recycler_refresh, null); // view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, // LayoutParams.WRAP_CONTENT));  return new ItemHolder(view);  } // type == TYPE_FOOTER 返回footerView  else if (viewType == TYPE_FOOTER) { View view = LayoutInflater.from(parent.getContext()).inflate( R.layout.item_recycler_footer, null); // view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, // LayoutParams.WRAP_CONTENT));  return new FooterHolder(view);  } return null;  } @Override  public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof ItemHolder) { ItemHolder itemHolder = (ItemHolder) holder;  itemHolder.textView.setText(mDatas.get(position));  } else if (holder instanceof FooterHolder) { FooterHolder footHolder = (FooterHolder) holder;  //这句如果不注释,那么底部就会有添加的一个item  footHolder.linearLayout.setVisibility(View.GONE);  switch (load_more_status) { case PULLUP_LOAD_MORE: footHolder.linearLayout.setVisibility(View.GONE); // footHolder.textView.setText("已经到底了");  break;  case LOADING_MORE: footHolder.linearLayout.setVisibility(View.VISIBLE);  footHolder.textView.setText("正在加载更多数据...");  break;  } } } @Override  public int getItemCount() { return mDatas == null ? 0 : mDatas.size() + 1;  } @Override  public int getItemViewType(int position) { // 最后一个item设置为footerView  if (position + 1 == getItemCount()) { return TYPE_FOOTER;  } else { return TYPE_ITEM;  } } class ItemHolder extends RecyclerView.ViewHolder { public TextView textView;   public ItemHolder(View itemView) { super(itemView);  textView = (TextView) itemView.findViewById(R.id.tv_item_recycler_refresh);  } } class FooterHolder extends RecyclerView.ViewHolder { public TextView textView;  public LinearLayout linearLayout;   public FooterHolder(View itemView) { super(itemView);  textView = (TextView) itemView.findViewById(R.id.tv_item_recycler_footer);  linearLayout = (LinearLayout) itemView.findViewById(R.id.ll_item_recycler_footer);  } } /**  * //上拉加载更多  * PULLUP_LOAD_MORE=0;  * //正在加载中  * LOADING_MORE=1;  * //加载完成已经没有更多数据了  * NO_MORE_DATA=2;  *  * @param status  */  public void changeMoreStatus(int status) { load_more_status = status;  notifyDataSetChanged();  } } 
而对RecyclerView的上拉加载,我们这样实现:
 mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override  public void onScrollStateChanged(RecyclerView recyclerView,  int newState) { super.onScrollStateChanged(recyclerView, newState);  if (newState == RecyclerView.SCROLL_STATE_IDLE  && lastVisibleItem + 1 == mAdapter.getItemCount()) { Log.i(">>>>>", ">>>>" + lastVisibleItem + ">>>" + mAdapter.getItemCount());  mAdapter.changeMoreStatus(mAdapter.LOADING_MORE);  //为了有刷新的效果,延迟2s修改状态  new Handler().postDelayed(new Runnable() { @Override  public void run() { mAdapter.changeMoreStatus(RefreshAdapter1.PULLUP_LOAD_MORE);  //实际项目中这里一般是用网络请求获取数据  mList.add("上拉加载");  } }, 2000);  } } @Override  public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy);  //判断是当前layoutManager是否为LinearLayoutManager  // 只有LinearLayoutManager才有查找第一个和最后一个可见view位置的方法  if (linearLayoutManager instanceof LinearLayoutManager) { //获取最后一个可见view的位置  lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();  //获取第一个可见view的位置 // int firstItemPosition = linearLayoutManager.findFirstVisibleItemPosition();  } } });  } 
最终效果如下:

不过,现在也有点bug,如果列表没有占满屏幕的话,下拉刷新的时候也会同时触发上拉加载的效果,大家如果有好的解决方案的话可以给我说下,先谢谢了
参考:


原文链接:https://yq.aliyun.com/articles/680460
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章