美文网首页
SwipeRefreshLayout+RecyclerView+

SwipeRefreshLayout+RecyclerView+

作者: 罗罗罗罗罗sky | 来源:发表于2016-08-22 16:40 被阅读1048次

    前言

    在我们的App中,经常会存在各种列表,在RecyclerView之前,往往我们会使用ListView来做。然后再用其他的下拉刷新控件,而从Google提供SwipeRefreshLayout和RecyclerView之后,我们往往会采取二者相结合的方式来做列表显示和下拉刷新,至于有点我就不在这里一一列举,总之方便很多。我在前一篇博客中提到过如何的去搭建一个列表刷新框架,具体的来讲我们需要考虑到一下几点:

    1.是否可以将SwipeRefreshLayout和RecyclerView进行绑定,并对外提供下拉刷新和上拉加载的回调接口
    2.是否可以添加头布局和脚部局
    3.缺省页如何加,如何更好的控制
    4.如何去简化Adapter,对子类提供部分抽象方法
    5.如何减少分页逻辑代码,刷新数据分为全局刷新和局部刷新等等
    ............
    

    废话少说,下面我们具体的来分析一下:
    PullLoadMoreRecyclerView.java

    package main.ui.com.pullrefreshlayout;
    import android.content.Context;
    import android.support.v4.widget.SwipeRefreshLayout;
    import android.support.v7.widget.DefaultItemAnimator;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.support.v7.widget.StaggeredGridLayoutManager;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.LinearLayout;
    
    /** * Author:${luomingjun} 
    * 时间:2016/2/29 09:53
     * 带下拉刷新 上拉加载更多
     */
    public class PullLoadMoreRecyclerView extends LinearLayout {    
        private RecyclerView mRecyclerView;  //RecyclerView 
        private PullRefreshLayout mSwipeRefreshLayout; // SwipeRefreshLaout
        private PullLoadMoreListener mPullLoadMoreListener;//加载更多 下拉刷新回调监听
     
       private boolean hasMore = true; 
       private boolean isRefresh = false; 
       private boolean isLoadMore = false;
       private LinearLayout mFooterView;
       private Context mContext;
    
      public PullLoadMoreRecyclerView(Context context) { 
           super(context);
            initView(context);
        } 
    
      public PullLoadMoreRecyclerView(Context context, AttributeSet attrs) {  
          super(context, attrs);
            initView(context);
        }
    
      private void initView(Context context) {
          mContext = context; 
          View view = LayoutInflater.from(context).inflate(R.layout.pull_loadmore_layout, null);
    
          mSwipeRefreshLayout = (PullRefreshLayout) view.findViewById(R.id.swipeRefreshLayout);      mSwipeRefreshLayout.setColorSchemeResources(R.color.bg_color_009bff); 
          mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayoutOnRefresh(this));
     
          mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
          mRecyclerView.setVerticalScrollBarEnabled(true); 
          mRecy clerView.setHasFixedSize(true);
          mRecyclerView.setItemAnimator(new DefaultItemAnimator());
          mRecyclerView.setOnScrollListener(new RecyclerViewOnScroll(this));
            mRecyclerView.setOnTouchListener( 
                   new OnTouchListener() {
                        @Override                   
              public boolean onTouch(View v, MotionEvent event) { 
                           return isRefresh; 
                       }   
                 }   
         );  
        
        /*** 脚布局  ***/
        mFooterView = (LinearLayout)view.findViewById(R.id.footer_linearlayout); 
        mFooterView.setVisibility(View.GONE);  
        this.addView(view);  
      }  
    
      /**    
       * LinearLayoutManager
       */ 
       public void setLinearLayout() {  
          LinearLayoutManagerWrapper linearLayoutManager = new  LinearLayoutManagerWrapper(mContext);   
          linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);      
          mRecyclerView.setLayoutManager(linearLayoutManager); 
       }   
    
     /**    
      * GridLayoutManager 
      */    
        public void setGridLayout(int spanCount) { 
          GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, spanCount);     
          gridLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);  
          mRecyclerView.setLayoutManager(gridLayoutManager);
       }   
    
       /**  
       * StaggeredGridLayoutManager
       */
          public void setStaggeredGridLayout(int spanCount) {   
           StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(spanCount, LinearLayoutManager.VERTICAL);  
           mRecyclerView.setLayoutManager(staggeredGridLayoutManager); 
       }  
    
      /**  
       * addItemDecoration   定制分割线
        */
        public void addItemDecoration(int drawble) {  
          mRecyclerView.addItemDecoration(new DividerItemDecoration(getContext(), LinearLayoutManager.VERTICAL,drawble)); 
       }  
    
      public void setPullRefreshEnable(boolean enable) {
            mSwipeRefreshLayout.setEnabled(enable);  
      }    
    
       public boolean getPullRefreshEnable() {
            return mSwipeRefreshLayout.isEnabled(); 
       } 
    
       /**    
       * 得到LayoutManager
       *  * @return LayoutManager 
       */   
       public RecyclerView.LayoutManager getLayoutManager() {  
          return mRecyclerView.getLayoutManager();
        }   
    
      /** 
        * @return RecyclerView   
        */ 
       public RecyclerView getRecyclerView() {
            return mRecyclerView;  
      } 
    
       /**   
        * @return SwipeRefreshLayout 
        */   
      public SwipeRefreshLayout getSwipeRefreshLayout() {  
          return mSwipeRefreshLayout; 
       }   
    
       /**     
          * 设置加载更多 
         */  
      public void loadMore() {  
          if (mPullLoadMoreListener != null && hasMore) {  
              mFooterView.setVisibility(View.VISIBLE);
                mPullLoadMoreListener.onLoadMore(); 
           }  
      }  
     
       /**     
         * 设置加载完成
         */
        public void setPullLoadMoreCompleted() { 
           isRefresh = false;
            mSetRefreshing(false);
            isLoadMore = false;  
          mFooterView.setVisibility(View.GONE); 
       }   
     
     /**   
       * 设置刷新完成   
       */ 
        public void mSetRefreshing(final boolean isRefreshing) {  
          isRefresh = false; 
           mSwipeRefreshLayout.post(new Runnable() {   
             @Override            
           public void run() {    
                mSwipeRefreshLayout.setRefreshing(isRefreshing); 
               }    
        });
        }  
    
      /** 
         * 上拉加载更多 下拉刷新的回调  
        */  
      public void setOnPullLoadMoreListener(PullLoadMoreListener listener) { 
           mPullLoadMoreListener = listener; 
      }  
    
      /**  
         * 设置下拉刷新
         */  
      public void refresh() {
            mRecyclerView.setVisibility(View.VISIBLE);    
        if (mPullLoadMoreListener != null) { 
               mPullLoadMoreListener.onRefresh(); 
           }  
      }  
    
      /**    
     * 滚动到顶部 
        */ 
       public void scrollToTop() {     
       mRecyclerView.scrollToPosition(0); 
       }   
    
     /**  
       * 设置适配器  
       *  
       * @param adapter adpater 
        */   
     public void setAdapter(RecyclerView.Adapter adapter) {   
         if (adapter != null) {      
          mRecyclerView.setAdapter(adapter);  
          }  
      }   
     /**   
      * 设置下拉刷新
         */   
     public void setmRefreshLayout(boolean isRefresh) {     
       mSwipeRefreshLayout.setIsRefresh(isRefresh); 
       }    
    
      /**  
        * 是否上拉加载更多
        *     * @return 
        */   
     public boolean isLoadMore() {  
          return isLoadMore; 
       }    
    
     /**    
       * 设置上拉加载更多的状态  
       * * @return  
       */
        public void setIsLoadMore(boolean isLoadMore) { 
           this.isLoadMore = isLoadMore; 
       }   
    
     /**   
       * 是否下拉刷新  
       *  * @return
         */  
      public boolean isRefresh() {  
          return isRefresh; 
       }   
     /**   
      * 设置下拉刷新的状态 
        *     * @return   
      */
        public void setIsRefresh(boolean isRefresh) {
            this.isRefresh = isRefresh;
        }   
     /**   
      * 是否还有很多
         *     * @return   
      */  
      public boolean isHasMore() { 
           return hasMore;   
     }    
    /**    
     * 设置更多状态 
        * 
        * @param hasMore  
       */  
      public void setHasMore(boolean hasMore) {
            this.hasMore = hasMore;   
     }  
      /**
         * 滑动到指定的postion 
        * @param position  
       */    
    public void smoothToPosition(int position) {  
          mRecyclerView.smoothScrollToPosition(position); 
       }
    }
    

    如上:我们已经了解了SwipeRefreshLayout和RecyclerView的结合使用,自定义了一个LinearLayout,接下来我们继续来看我们的BaseRecyclerAdapter。

    package main.ui.com.pullrefreshlayout;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.support.v7.widget.StaggeredGridLayoutManager;
    import android.view.View;
    import android.view.ViewGroup;
    import java.util.ArrayList;
    import java.util.List;
    
    /** * Author:${luomingjun} 
    * 时间:2016/2/29 13:18 
    * 自定义的BaseRecyclerAdapter 
    * 1.主要封装了添加header 
    * 2.提供了点击事件  不用在每个adapter里面再次去写点击事件(RecyclerView中点击事件必须实现接口) 
    * 3.  提供添加数据的两个函数方法    addReDatas(ArrayList<T> datas)       addReDatas(ArrayList<T> mDatas, int index, int count) 
    * 第一个函数 可以使用在不用分页或者加载第一页数据时候使用  它自带刷新列表  第二个方法适合在分页时候 使用 具体参数看注释 
    */
    
    public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
    public static final int TYPE_HEADER = 0;    
    public static final int TYPE_NORMAL = 1;    
    private List<T> mDatas = new ArrayList<>();  //数据源
    private View mHeaderView;    
    private OnItemClickListener mListener;
    
    /***
      *设置点击Item点击事件
      */
    public void setOnItemClickListener(OnItemClickListener li) { 
           mListener = li;
        } 
    
    //添加头(在item为0出插入头)
    public void setHeaderView(View headerView) { 
           mHeaderView = headerView;
            notifyItemInserted(0);
        } 
    
       /**    
     * 获得头部HeaderView    
     * @return View    
     */   
     public View getHeaderView() { 
           return mHeaderView;  
      } 
     
      /**    
     * 获得数据源
     * @return mDatas  
     */   
      public List<T> getListData() {  
          return mDatas;  
      }  
    
      @Override    
    public int getItemViewType(int position) {
            if (mHeaderView == null) 
             return TYPE_NORMAL;
            if (position == 0)
             return TYPE_HEADER; 
             return TYPE_NORMAL;
        }   
    
     @Override    
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {  
          if (mHeaderView != null && viewType == TYPE_HEADER)
           return new Holder(mHeaderView);  
            return onCreate(parent, viewType); 
       }    
    
    @Override
        public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {   
         if (getItemViewType(position) == TYPE_HEADER) return;  
          final int pos = getRealPosition(viewHolder); 
          final T data = mDatas.get(pos);  
          onBind(viewHolder, pos, data);  
          if (mListener != null) {
                viewHolder.itemView.setOnClickListener(new View.OnClickListener() {  
                  @Override         
                public void onClick(View v) {     
                   mListener.onItemClick(pos, data);
                    }    
           }); 
           }   
     } 
      
     @Override  
      public void onAttachedToRecyclerView(RecyclerView recyclerView) { 
           super.onAttachedToRecyclerView(recyclerView);   
         RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); 
           if (manager instanceof GridLayoutManager) { 
               final GridLayoutManager gridManager = ((GridLayoutManager) manager);
                gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {   
                 @Override             
              public int getSpanSize(int position) {    
                       return getItemViewType(position) == TYPE_HEADER  ? gridManager.getSpanCount() : 1;         
           }            });   
         }  
      } 
    
      @Override    
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {   
         super.onViewAttachedToWindow(holder);     
         ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();     
           if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams  && holder.getLayoutPosition() == 0) {   
             StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;         
             p.setFullSpan(true); 
           }   
     }    
    
     //获得真是的Position
     public int getRealPosition(RecyclerView.ViewHolder holder) {  
          int position = holder.getLayoutPosition();   
         return mHeaderView == null ? position : position - 1;  
      }  
    
      @Override  
      public int getItemCount() {     
           return mHeaderView == null ? mDatas.size() : mDatas.size() + 1;
        } 
    
       public abstract RecyclerView.ViewHolder onCreate(ViewGroup parent, final int viewType); 
       public abstract void onBind(RecyclerView.ViewHolder viewHolder, int RealPosition, T data);  
       public class Holder extends RecyclerView.ViewHolder {   
         public Holder(View itemView) { 
               super(itemView);   
          }
         }   
    
     /**    
     * 是否显示缺省页  
       *     * @return 
        */    
    public boolean blnDataBind() {  
          if (mDatas != null && mDatas.size() > 0) {  
              return false;   
         } else { 
               return true;  
          }  
      }  
    
      /**   
      * @param datas 数据源  
       */   
     public void addReDatas(List<T> datas) { 
            mDatas.clear();  
           mDatas.addAll(datas);    
         notifyDataSetChanged();  
      }   
    
     public void addDatas(List<T> datas) { 
           mDatas = datas;   
         notifyDataSetChanged(); 
       }   
    
     /**    
      *  插入数据  局部刷新
     * @param data      数据源     
     * @param pageCount 每页条数  
     */ 
      public void addReDatas(List<T> data, int pageCount) {   
          mDatas.addAll(data);    
          this.notifyItemRangeChanged(mDatas.size() - pageCount, pageCount); 
       }
    }
    

    在使用以上Adpater时候,需要注意以上的mDatas 才是真正的数据源,这样做的原因是为了简化分页时候的逻辑,往往我们在做分页时候,需要判断当前页,对数据源操作等等,而这里便不用,只需要分两种情况考虑,第一种就是刷新时候或者第一页时候,第二种就是分页数据,同样它解决了添加头的问题,直接将View插入positon为0的位置,RecyclerView的item点击事件等等。

    下面我们来看在MainActivity中的使用:
    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:id="@+id/layout_distribution_main"  
       android:layout_width="match_parent" 
       android:layout_height="match_parent"
       android:clipToPadding="true"  
       android:fitsSystemWindows="true" 
       android:orientation="vertical"> 
          <RelativeLayout       
                 android:id="@+id/rl_report_main" 
                 android:layout_width="match_parent"  
                 android:layout_height="wrap_content" 
                 android:background="@color/bg_color_fafafa"
            >     
         <main.ui.com.pullrefreshlayout.PullLoadMoreRecyclerView      
               android:id="@+id/pullLoadMoreRecyclerView" 
               android:layout_width="match_parent"    
               android:layout_height="wrap_content"
         />   
        <!-- 缺省页 -->   
         <include          
               layout="@layout/not_data_layout"      
               android:layout_width="wrap_content"  
              android:layout_height="wrap_content"  
              android:layout_centerInParent="true" 
     />   
     </RelativeLayout>
    </RelativeLayout>
    

    MainActivity.java

    package main.ui.com.pullrefreshlayout;
    import android.os.Bundle;
    import android.os.Handler;
    import android.support.v7.app.AppCompatActivity;
    import android.view.LayoutInflater;
    import android.view.View;
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainActivity extends AppCompatActivity implements PullLoadMoreListener {  
      private PullLoadMoreRecyclerView pullLoadMoreRecyclerView;  
      private DataAdapter adapter;  
      private List<DataEntity> data=new ArrayList<>(); 
       private static int page=1;   
     @Override   
     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);    
           setContentView(R.layout.activity_main);   
           pullLoadMoreRecyclerView = (PullLoadMoreRecyclerView) findViewById(R.id.pullLoadMoreRecyclerView);  
            View view = LayoutInflater.from(this).inflate(R.layout.distribution_revenue_head, null);
            pullLoadMoreRecyclerView.setLinearLayout();      
            pullLoadMoreRecyclerView.setmRefreshLayout(false); 
    
           adapter=new DataAdapter();    
           adapter.setHeaderView(view); 
    
           pullLoadMoreRecyclerView.setAdapter(adapter);   
           pullLoadMoreRecyclerView.setOnPullLoadMoreListener(this); 
       }   
    
       @Override   
     public void onRefresh() { 
        new Handler().postDelayed(new Runnable() {  
           @Override        
          public void run() {   
              page=1;  
               data.clear(); 
                for (int i = 0; i < 10; i++) {        
                 DataEntity dataEntity = new DataEntity();     
                 dataEntity.data = "测试" + i;      
                 data.add(dataEntity);   
              }        
             adapter.addDatas(data);     
             pullLoadMoreRecyclerView.setPullLoadMoreCompleted();  
           }   
      }, 2000);   
     }   
    
        @Override
        public void onLoadMore() {
            new Handler().postDelayed(new Runnable() {   
             @Override     
              public void run() {    
                page++;     
                   for (int i = data.size(); i < 10 * page; i++) {  
                      DataEntity dataEntity = new DataEntity();    
                     dataEntity.data = "测试" + i;     
                     data.add(dataEntity); 
                   }               
                adapter.addReDatas(data, page);    
                pullLoadMoreRecyclerView.setPullLoadMoreCompleted(); 
               }      
          },
         2000);
        }
    }
    

    我这里是模拟数据,所以写的比较乱,建议在UI界面里面不要做数据源,直接用addReDatas()方法和addDatas()方法进行数据在Adapter显示,另外在这里需要注意在用这部分代码时候,如果出现下拉刷新时候,动画出现悬停的情况,请检查工程是否依赖了v4jar包,以上为部分核心代码,注释没加太多,有问题在底部留言。

    源码传送门:http://pan.baidu.com/s/1kV6kzVD 提取码:engu

    相关文章

      网友评论

          本文标题:SwipeRefreshLayout+RecyclerView+

          本文链接:https://www.haomeiwen.com/subject/zkmusttx.html