• RecycleView 滑动到底部,加载更多


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

      然而在使用的过程中却遇到一些问题,基本现在手机页面都会有滑动到底部加载更多的功能,而RecycleView 并没有提供像ListView的addFooter等方法,所以实现起来还是有点麻烦。经过一段时间的摸索,终于找到实现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     public 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     //瀑布流
     19     private StaggeredGridLayoutManager mStaggeredGridLayoutManager;
     20     //数据集
     21     private CircularArray<T> mTs;
     22     //首次进入
     23     private boolean mFirstEnter = true;
     24     private RecyclerView mRecyclerView;
     25 
     26     public BaseLoadingAdapter(RecyclerView recyclerView, CircularArray<T> ts) {
     27 
     28         mTs = ts;
     29 
     30         mRecyclerView = recyclerView;
     31 
     32         setSpanCount(recyclerView);
     33 
     34         //notifyLoading();
     35     }
     36 
     37     private OnLoadingListener mOnLoadingListener;
     38 
     39     /**
     40      * 加载更多接口
     41      */
     42     public interface OnLoadingListener {
     43         void loading();
     44     }
     45 
     46     /**
     47      * 设置监听接口
     48      *
     49      * @param onLoadingListener onLoadingListener
     50      */
     51     public void setOnLoadingListener(OnLoadingListener onLoadingListener) {
     52         setScrollListener(mRecyclerView);
     53         mOnLoadingListener = onLoadingListener;
     54     }
     55 
     56     /**
     57      * 加载完成
     58      */
     59     public void setLoadingComplete() {
     60         if (mTs.size() > 0 && mTs.getLast() == null) {
     61             mIsLoading = false;
     62             mTs.removeFromEnd(1);
     63             notifyItemRemoved(mTs.size() - 1);
     64         }
     65     }
     66 
     67     /**
     68      * 没有更多数据
     69      */
     70     public void setLoadingNoMore() {
     71         mIsLoading = false;
     72         if (mLoadingViewHolder != null) {
     73             mLoadingViewHolder.progressBar.setVisibility(View.GONE);
     74             mLoadingViewHolder.tvLoading.setText("已加载完!");
     75         }
     76     }
     77 
     78     /**
     79      * 加载失败
     80      */
     81     public void setLoadingError() {
     82         if (mLoadingViewHolder != null) {
     83             mIsLoading = false;
     84             mLoadingViewHolder.progressBar.setVisibility(View.GONE);
     85             mLoadingViewHolder.tvLoading.setText("加载失败,点击重新加载!");
     86 
     87             mLoadingViewHolder.tvLoading.setOnClickListener(new View.OnClickListener() {
     88                 @Override
     89                 public void onClick(View v) {
     90                     if (mOnLoadingListener != null) {
     91                         mIsLoading = true;
     92                         mLoadingViewHolder.progressBar.setVisibility(View.VISIBLE);
     93                         mLoadingViewHolder.tvLoading.setText("正在加载...");
     94 
     95                         mOnLoadingListener.loading();
     96                     }
     97                 }
     98             });
     99         }
    100     }
    101 
    102     /**
    103      * @return Whether it is possible for the child view of this layout to
    104      * scroll up. Override this if the child view is a custom view.
    105      */
    106     private boolean canScrollDown(RecyclerView recyclerView) {
    107         return ViewCompat.canScrollVertically(recyclerView, 1);
    108     }
    109 
    110     /**
    111      * 设置加载item占据一行
    112      *
    113      * @param recyclerView recycleView
    114      */
    115     private void setSpanCount(RecyclerView recyclerView) {
    116         RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
    117 
    118         if (layoutManager == null) {
    119             Log.e(TAG, "LayoutManager 为空,请先设置 recycleView.setLayoutManager(...)");
    120         }
    121 
    122         //网格布局
    123         if (layoutManager instanceof GridLayoutManager) {
    124             final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
    125             gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    126                 @Override
    127                 public int getSpanSize(int position) {
    128                     int type = getItemViewType(position);
    129                     if (type == TYPE_NORMAL_ITEM) {
    130                         return 1;
    131                     } else {
    132                         return gridLayoutManager.getSpanCount();
    133                     }
    134                 }
    135             });
    136         }
    137 
    138         //瀑布流布局
    139         if (layoutManager instanceof StaggeredGridLayoutManager) {
    140             mStaggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
    141         }
    142     }
    143 
    144     /**
    145      * 显示加载
    146      */
    147     private void notifyLoading() {
    148         if (mTs.size() != 0 && mTs.getLast() != null) {
    149             mTs.addLast(null);
    150             notifyItemInserted(mTs.size() - 1);
    151         }
    152     }
    153 
    154     /**
    155      * 监听滚动事件
    156      *
    157      * @param recyclerView recycleView
    158      */
    159     private void setScrollListener(RecyclerView recyclerView) {
    160         if(recyclerView == null) {
    161             Log.e(TAG, "recycleView 为空");
    162             return;
    163         }
    164 
    165         recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    166             @Override
    167             public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    168                 super.onScrollStateChanged(recyclerView, newState);
    169             }
    170 
    171             @Override
    172             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    173                 super.onScrolled(recyclerView, dx, dy);
    174 
    175                 if (!canScrollDown(recyclerView)) {
    176 
    177                     //首次进入不加载
    178                     if (!mIsLoading && !mFirstEnter) {
    179 
    180                         notifyLoading();
    181 
    182                         mIsLoading = true;
    183 
    184                         if (mLoadingViewHolder != null) {
    185                             mLoadingViewHolder.progressBar.setVisibility(View.VISIBLE);
    186                             mLoadingViewHolder.tvLoading.setText("正在加载...");
    187                         }
    188 
    189                         if (mOnLoadingListener != null) {
    190                             mOnLoadingListener.loading();
    191                         }
    192                     }
    193                 }
    194 
    195                 if (mFirstEnter) {
    196                     mFirstEnter = false;
    197                 }
    198             }
    199         });
    200     }
    201 
    202     /**
    203      * 创建viewHolder
    204      *
    205      * @param parent viewGroup
    206      * @return viewHolder
    207      */
    208     public abstract RecyclerView.ViewHolder onCreateNormalViewHolder(ViewGroup parent);
    209 
    210     /**
    211      * 绑定viewHolder
    212      *
    213      * @param holder   viewHolder
    214      * @param position position
    215      */
    216     public abstract void onBindNormalViewHolder(RecyclerView.ViewHolder holder, int position);
    217 
    218     /**
    219      * 加载布局
    220      */
    221     private class LoadingViewHolder extends RecyclerView.ViewHolder {
    222         public ProgressBar progressBar;
    223         public TextView tvLoading;
    224         public LinearLayout llyLoading;
    225 
    226         public LoadingViewHolder(View view) {
    227             super(view);
    228 
    229             progressBar = (ProgressBar) view.findViewById(R.id.progress_loading);
    230             tvLoading = (TextView) view.findViewById(R.id.tv_loading);
    231             llyLoading = (LinearLayout) view.findViewById(R.id.lly_loading);
    232         }
    233     }
    234 
    235     @Override
    236     public int getItemViewType(int position) {
    237         T t = mTs.get(position);
    238         if (t == null) {
    239             return TYPE_LOADING_ITEM;
    240         } else {
    241             return TYPE_NORMAL_ITEM;
    242         }
    243     }
    244 
    245     @Override
    246     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    247         if (viewType == TYPE_NORMAL_ITEM) {
    248             return onCreateNormalViewHolder(parent);
    249         } else {
    250             View view = LayoutInflater.from(parent.getContext()).inflate(
    251                     R.layout.loading_layout, parent, false);
    252             mLoadingViewHolder = new LoadingViewHolder(view);
    253             return mLoadingViewHolder;
    254         }
    255     }
    256 
    257     @Override
    258     public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    259         int type = getItemViewType(position);
    260         if (type == TYPE_NORMAL_ITEM) {
    261             onBindNormalViewHolder(holder, position);
    262         } else {
    263 
    264             if (mStaggeredGridLayoutManager != null) {
    265                 StaggeredGridLayoutManager.LayoutParams layoutParams =
    266                         new StaggeredGridLayoutManager.LayoutParams(
    267                                 ViewGroup.LayoutParams.MATCH_PARENT,
    268                                 ViewGroup.LayoutParams.WRAP_CONTENT);
    269                 layoutParams.setFullSpan(true);
    270 
    271                 mLoadingViewHolder.llyLoading.setLayoutParams(layoutParams);
    272             }
    273         }
    274     }
    275 
    276     @Override
    277     public int getItemCount() {
    278         return mTs.size();
    279     }
    280 }
    Base Loading Adapter

          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     @Override
    29     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     @Override
    36     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 }
    Sample

          

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

  • 相关阅读:
    寒假第七天
    寒假第六天
    寒假第五天
    寒假第四天
    leetcode 105 从前序与中序遍历序列构造二叉树
    leetcode 268 丢失的数字
    leetcode 141 环形链表
    判断顶点是否在三角形内部
    java 基本数据类型
    leetcode 20 有效的括号
  • 原文地址:https://www.cnblogs.com/SWDreaming/p/5023339.html
Copyright © 2020-2023  润新知