你的位置:首页 > 操作系统

[操作系统]RecycleView 滑动到底部,加载更多


  android.support.v7 包提供了一个新的组件:RecycleView,用以提供一个灵活的列表试图、显示大型数据集,它支持局部刷新、显示动画等功能,可以用来取代ListView与GridView.

  然后在使用的过程中却遇到一些问题,基本现在手机页面都会有滑动到底部加载更多的功能,而RecycleView 并没有提供像ListView的addFooter等方法,所以实现起来还是有点麻烦,虽然喜欢RecycleView的强大功能,但不得不因此而放弃。经过一段时间的摸索,终于找到实现RecycleView加载更多的方法。

  本文主要通过RecycleView 的ItemViewType 来实现RecycleView活动到底部加载更多功能,支持 列表、网格、瀑布流等布局。

 

  根据ItemViewType创建两种布局,一个用于显示正常内容的布局,一个用于加载布局,然后监听RecycleView的滚动事件,当滑动到底部时添加加载布局,对于列表布局来说很简单,不再熬述,然而对于网格布局与瀑布流布局来说,要解决"加载布局只占用一列"的问题,

  1.对于网格布局,GridLayoutManager 提供了一个 setSpanSizeLookup() 的方法,用来设置每个条目可以占用的列数,默认为1.

  2.对于瀑布流,StaggeredGridLayoutManager 提供了一个 StaggeredGridLayoutManager.LayoutParams 内部静态类,此类中有一个setFullSpan() 方法,用来设置条目跨越全列。

  

  3.基类的实现方式如下:子类只需要重写以下方法:

    onCreateNormalViewHolder(ViewGroup parent);

    onBindNormalViewHolder(RecyclerView.ViewHolder holder, int position);

    

 1 /** 2  * Created by sunwei on 2015/12/4. 3  * Email: lx_sunwei@163.com. 4  * Description: recycleView 滑动到底部加载更多 5 */ 6 public abstract class BaseLoadingAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> { 7  8   private static final String TAG = "BaseLoadingAdapter"; 9  10   //是否正在加载 11   private boolean mIsLoading = false; 12   //正常条目 13   private static final int TYPE_NORMAL_ITEM = 0; 14   //加载条目 15   private static final int TYPE_LOADING_ITEM = 1; 16   //加载viewHolder 17   private LoadingViewHolder mLoadingViewHolder; 18   private StaggeredGridLayoutManager mStaggeredGridLayoutManager; 19   //数据集 20   private CircularArray<T> mTs; 21  22   public BaseLoadingAdapter(RecyclerView recyclerView, CircularArray<T> ts) { 23     mTs = ts; 24  25     setSpanCount(recyclerView); 26  27     setScrollListener(recyclerView); 28   } 29  30   private OnLoadingListener mOnLoadingListener; 31  32   /** 33    * 加载更多接口 34   */ 35   public interface OnLoadingListener { 36     void loading(); 37   } 38  39   /** 40    * 设置监听接口 41    * 42    * @param onLoadingListener onLoadingListener 43   */ 44   public void setOnLoadingListener(OnLoadingListener onLoadingListener) { 45     mOnLoadingListener = onLoadingListener; 46   } 47  48   /** 49    * 加载完成 50   */ 51   public void setLoadingComplete() { 52     mIsLoading = false; 53     mTs.removeFromEnd(1); 54     notifyItemRemoved(mTs.size() - 1); 55   } 56  57   /** 58    * 没有更多数据 59   */ 60   public void setLoadingNoMore() { 61     mLoadingViewHolder.progressBar.setVisibility(View.GONE); 62     mLoadingViewHolder.tvLoading.setText("数据已加载完!"); 63   } 64  65   /** 66    * 加载失败 67   */ 68   public void setLoadingError() { 69     if (mLoadingViewHolder != null) { 70       mLoadingViewHolder.progressBar.setVisibility(View.GONE); 71       mLoadingViewHolder.tvLoading.setText("加载失败,点击重新加载!"); 72  73       mLoadingViewHolder.tvLoading.setOnClickListener(new View.OnClickListener() { 74         @Override 75         public void onClick(View v) { 76           if (mOnLoadingListener != null) { 77             mLoadingViewHolder.progressBar.setVisibility(View.VISIBLE); 78             mLoadingViewHolder.tvLoading.setText("正在加载"); 79  80             mOnLoadingListener.loading(); 81           } 82         } 83       }); 84     } 85   } 86  87   /** 88    * @return Whether it is possible for the child view of this layout to 89    * scroll up. Override this if the child view is a custom view. 90   */ 91   private boolean canScrollDown(RecyclerView recyclerView) { 92     return ViewCompat.canScrollVertically(recyclerView, 1); 93   } 94  95   /** 96    * 设置每个条目占用的列数 97    * 98    * @param recyclerView recycleView 99   */100   private void setSpanCount(RecyclerView recyclerView) {101     RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();102     if (layoutManager instanceof GridLayoutManager) {103       final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;104       gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {105         @Override106         public int getSpanSize(int position) {107           int type = getItemViewType(position);108           if (type == TYPE_NORMAL_ITEM) {109             return 1;110           } else {111             return gridLayoutManager.getSpanCount();112           }113         }114       });115     }116 117     if (layoutManager instanceof StaggeredGridLayoutManager) {118       mStaggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;119     }120   }121 122   /**123    * 监听滚动事件124    *125    * @param recyclerView recycleView126   */127   private void setScrollListener(RecyclerView recyclerView) {128     recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {129       @Override130       public void onScrollStateChanged(RecyclerView recyclerView, int newState) {131         super.onScrollStateChanged(recyclerView, newState);132       }133 134       @Override135       public void onScrolled(RecyclerView recyclerView, int dx, int dy) {136         super.onScrolled(recyclerView, dx, dy);137 138         if (!canScrollDown(recyclerView)) {139           if (!mIsLoading) {140             mIsLoading = true;141             mTs.addLast(null);142             notifyItemInserted(mTs.size() - 1);143             if (mOnLoadingListener != null) {144               mOnLoadingListener.loading();145             }146           }147         }148       }149     });150   }151 152   /**153    * 创建viewHolder154    *155    * @param parent viewGroup156    * @return viewHolder157   */158   public abstract RecyclerView.ViewHolder onCreateNormalViewHolder(ViewGroup parent);159 160   /**161    * 绑定viewHolder162    *163    * @param holder  viewHolder164    * @param position position165   */166   public abstract void onBindNormalViewHolder(RecyclerView.ViewHolder holder, int position);167 168   /**169    * 加载布局170   */171   private class LoadingViewHolder extends RecyclerView.ViewHolder {172     public ProgressBar progressBar;173     public TextView tvLoading;174     public LinearLayout llyLoading;175 176     public LoadingViewHolder(View view) {177       super(view);178 179       progressBar = (ProgressBar) view.findViewById(R.id.progress_loading);180       tvLoading = (TextView) view.findViewById(R.id.tv_loading);181       llyLoading = (LinearLayout) view.findViewById(R.id.lly_loading);182     }183   }184 185   @Override186   public int getItemViewType(int position) {187     T t = mTs.get(position);188     if (t == null) {189       return TYPE_LOADING_ITEM;190     } else {191       return TYPE_NORMAL_ITEM;192     }193   }194 195   @Override196   public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {197     if (viewType == TYPE_NORMAL_ITEM) {198       return onCreateNormalViewHolder(parent);199     } else {200       View view = LayoutInflater.from(parent.getContext()).inflate(201           R.layout.loading_view, parent, false);202       mLoadingViewHolder = new LoadingViewHolder(view);203       return mLoadingViewHolder;204     }205   }206 207   @Override208   public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {209     int type = getItemViewType(position);210     if (type == TYPE_NORMAL_ITEM) {211       onBindNormalViewHolder(holder, position);212     } else {213       if (mStaggeredGridLayoutManager != null) {214         StaggeredGridLayoutManager.LayoutParams layoutParams =215             new StaggeredGridLayoutManager.LayoutParams(216                 ViewGroup.LayoutParams.MATCH_PARENT,217                 ViewGroup.LayoutParams.WRAP_CONTENT);218         layoutParams.setFullSpan(true);219 220         mLoadingViewHolder.llyLoading.setLayoutParams(layoutParams);221       }222     }223   }224 225   @Override226   public int getItemCount() {227     return mTs.size();228   }229 }

 

  4.一个简单的列子

    

 1 /** 2  * Created by sunwei on 2015/12/4. 3  * Email: lx_sunwei@163.com. 4  * Description: 加载更多 5 */ 6 public class DesignLoaderMoreAdapter extends BaseLoadingAdapter<DesignItem> { 7  8   private CircularArray<DesignItem> mDesignItems; 9 10   public DesignLoaderMoreAdapter(RecyclerView recyclerView, CircularArray<DesignItem> datas) {11     super(recyclerView, datas);12 13     mDesignItems = datas;14   }15 16   //正常条目17   public class DesignViewHolder extends RecyclerView.ViewHolder {18     public TextView textView;19     public CardView cardView;20     public DesignViewHolder(View view) {21       super(view);22       textView = (TextView) view.findViewById(R.id.tv_design);23       cardView = (CardView) view.findViewById(R.id.cardView_designer);24 25     }26   }27 28   @Override29   public RecyclerView.ViewHolder onCreateNormalViewHolder(ViewGroup parent) {30     View view = LayoutInflater.from(parent.getContext()).inflate(31         R.layout.list_item_design, parent, false);32     return new DesignViewHolder(view);33   }34 35   @Override36   public void onBindNormalViewHolder(RecyclerView.ViewHolder holder, int position) {37     DesignViewHolder viewHolder = (DesignViewHolder)holder;38     DesignItem designItem = mDesignItems.get(position);39     if (position == 10) {40       //设置瀑布流的条目大小41       LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(260, 360);42       lp.setMargins(10, 40, 10, 80);43       viewHolder.cardView.setLayoutParams(lp);44     }45 46     viewHolder.textView.setText(designItem.name);47   }48 }

 

      

 

项目地址:https://github.com/lxsunwei/MaterialDesignDemo