【android】自定义组合控件PullToRefreshRecyeclerView

来源:互联网 发布:上海哪家java培训机构 编辑:程序博客网 时间:2024/06/02 07:31

场景:自从Android 5.0发布以来,越来越多的开发者开始接触RecyeclerView,但是RecyclerView如何实现下拉刷新,上拉加在更多。于是我就偷懒 写了一个,以供大家参考和学习,以待大家改进。



构思:想必大家对SwipeRefreshLayout这个控件有一定了解,没错本次自定义组合控件也就是SwipeRefreshLayout与RecyeclerView的组合。

那么我们一步一步来实现:

1.首先写一个组合布局如下:pulltorefreshrecyclerview.xml

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="@android:color/white"  
  6.     android:orientation="vertical" >  
  7.   
  8.   
  9.     <android.support.v4.widget.SwipeRefreshLayout  
  10.         android:id="@+id/all_swipe"  
  11.         android:layout_width="match_parent"  
  12.         android:layout_height="match_parent" >  
  13.   
  14.         <android.support.v7.widget.RecyclerView  
  15.             android:id="@+id/recycler_view"  
  16.             android:layout_width="match_parent"  
  17.             android:layout_height="match_parent"  
  18.             android:scrollbars="vertical" />  
  19.     </android.support.v4.widget.SwipeRefreshLayout>  
  20.   
  21. </LinearLayout>  
2.声明一个类PulltoRefreshRecyclerView.java继承自LinearLayout

a.声明一个接口

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public interface RefreshLoadMoreListener {  
  2.         public void onRefresh();  
  3.   
  4.         public void onLoadMore();  
  5.     }  
在Activity或者Fragment中去实现PulltoRefreshRecyclerView.RefreshLoadMoreListener接口

在PulltoRefreshRecyclerView调用刷新和加在更多,实质上是回调Activity或者Fragment实现的接口方法。

b.即 在PulltoRefreshRecyclerView有loadMore和refresh方法

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public void loadMore() {  
  2.         if (mRefreshLoadMoreListner != null && hasMore) {  
  3.             mRefreshLoadMoreListner.onLoadMore();  
  4.               
  5.         }  
  6.     }  
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public void refresh() {  
  2.         if (mRefreshLoadMoreListner != null) {  
  3.             mRefreshLoadMoreListner.onRefresh();  
  4.         }  
  5.     }  
c.那么就需要拿到这个实现的刷新加载监听实例

PulltoRefreshRecyclerView实现一个设置监听的方法

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public void setRefreshLoadMoreListener(RefreshLoadMoreListener listener) {  
  2.         mRefreshLoadMoreListner = listener;  
  3.     }  

d.RecyeclerView是基于Adapter的开发,那么这里也需要可以设置Adapter

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public void setAdapter(RecyclerView.Adapter adapter) {  
  2.         if (adapter != null)  
  3.             recyclerView.setAdapter(adapter);  
  4.     }  

e.考虑一下特殊的需求,有时禁止刷新,有时禁止加载更多那么我们来完善一下

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public void setPullLoadMoreEnable(boolean enable) {  
  2.         this.hasMore = enable;  
  3.     }  
  4.   
  5. public boolean getPullLoadMoreEnable() {  
  6.         return hasMore;  
  7.     }  
  8.   
  9. public void setPullRefreshEnable(boolean enable) {  
  10.         swipeRfl.setEnabled(enable);  
  11.     }  
  12.   
  13. public boolean getPullRefreshEnable() {  
  14.         return swipeRfl.isEnabled();  
  15.     }  
只要对相应的enable传入true或false则可进行开关控制

f.RecyeclerView可以是水平也可以是垂直,把这项功能也加入一下默认我们就让它为垂直


[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public void setOrientation(int orientation) {  
  2.         if (orientation != 0 && orientation != 1) {  
  3.             layoutManager.setOrientation(VERTICAL);  
  4.         } else {  
  5.             layoutManager.setOrientation(HORIZONTAL);  
  6.         }  
  7.     }  
  8.   
  9. public int getOrientation() {  
  10.         return layoutManager.getOrientation();  
  11.     }  

7.SwipeRefreshLayout的停止刷新效果

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public void stopRefresh() {  
  2.         isRefresh = false;  
  3.         swipeRfl.setRefreshing(false);  
  4.     }  

g.刷新原理和加载更多原理

刷新实际上是添加SwipeRefreshLayout的OnRefreshListener监听,在符合!isRefresh的前提下回调RefreshLoadMoreListener的onRefresh方法

加载更多原理是添加RecyeclerView的OnScrollListener监听,在符合hasMore且显示最后一项的前提下回调

RefreshLoadMoreListener的onLoadMore方法



2.那么我们来看看具体的PulltoRefreshRecyclerView代码

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. package com.jabony.recyclerpulltorefresh;  
  2.   
  3. import android.content.Context;  
  4. import android.support.v4.widget.SwipeRefreshLayout;  
  5. import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;  
  6. import android.support.v7.widget.LinearLayoutManager;  
  7. import android.support.v7.widget.RecyclerView;  
  8. import android.util.AttributeSet;  
  9. import android.view.LayoutInflater;  
  10. import android.widget.LinearLayout;  
  11. /** 
  12.  *  
  13.  * @author jabony 
  14.  * @since 2015年3月31日 16:06:59 
  15.  * 
  16.  */  
  17. public class PulltoRefreshRecyclerView extends LinearLayout {  
  18.     /** 
  19.      * 垂直方向 
  20.      */  
  21.     static final int VERTICAL = LinearLayoutManager.VERTICAL;  
  22.     /** 
  23.      * 水平方向 
  24.      */  
  25.     static final int HORIZONTAL = LinearLayoutManager.HORIZONTAL;  
  26.     /** 
  27.      * 内容控件 
  28.      */  
  29.     private RecyclerView recyclerView;  
  30.     /** 
  31.      * 刷新布局控件 
  32.      */  
  33.     private SwipeRefreshLayout swipeRfl;  
  34.     private LinearLayoutManager layoutManager;  
  35.     /* 
  36.      * 刷新布局的监听 
  37.      */  
  38.     private OnRefreshListener mRefreshListener;  
  39.     /** 
  40.      * 内容控件滚动监听  
  41.      */  
  42.     private RecyclerView.OnScrollListener mScrollListener;  
  43.     /** 
  44.      * 内容适配器 
  45.      */  
  46.     private RecyclerView.Adapter mAdapter;  
  47.     /* 
  48.      * 刷新加载监听事件 
  49.      */  
  50.     private RefreshLoadMoreListener mRefreshLoadMoreListner;  
  51.     /** 
  52.      * 是否可以加载更多 
  53.      */  
  54.     private boolean hasMore = true;  
  55.     /** 
  56.      * 是否正在刷新 
  57.      */  
  58.     private boolean isRefresh = false;  
  59.     /** 
  60.      * 是否正在加载更多 
  61.      */  
  62.     private boolean isLoadMore = false;  
  63.   
  64.     public PulltoRefreshRecyclerView(Context context) {  
  65.         super(context);  
  66.         // TODO Auto-generated constructor stub  
  67.     }  
  68.   
  69.     @SuppressWarnings("deprecation")  
  70.     public PulltoRefreshRecyclerView(Context context, AttributeSet attrs) {  
  71.         super(context, attrs);  
  72.         // 导入布局  
  73.         LayoutInflater.from(context).inflate(  
  74.                 R.layout.pulltorefreshrecyclerview, thistrue);  
  75.         swipeRfl = (SwipeRefreshLayout) findViewById(R.id.all_swipe);  
  76.         recyclerView = (RecyclerView) findViewById(R.id.recycler_view);  
  77.         // 加载颜色是循环播放的,只要没有完成刷新就会一直循环,color1>color2>color3>color4  
  78.         // swipeRfl.setColorScheme(Color.BLUE, Color.GREEN, Color.RED,  
  79.         // Color.YELLOW);  
  80.   
  81.         /** 
  82.          * 监听上拉至底部滚动监听 
  83.          */  
  84.         mScrollListener = new RecyclerView.OnScrollListener() {  
  85.             @Override  
  86.             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {  
  87.                 super.onScrolled(recyclerView, dx, dy);  
  88.                 //最后显示的项  
  89.                 int lastVisibleItem = layoutManager  
  90.                         .findLastVisibleItemPosition();  
  91.                 int totalItemCount = layoutManager.getItemCount();  
  92.                 // lastVisibleItem >= totalItemCount - 4 表示剩下4个item自动加载  
  93.                 // dy>0 表示向下滑动  
  94.                 /*  if (hasMore && (lastVisibleItem >= totalItemCount - 1) 
  95.                         && dy > 0 && !isLoadMore) { 
  96.                     isLoadMore = true; 
  97.                     loadMore(); 
  98.                 }*/  
  99.                 /** 
  100.                  * 无论水平还是垂直 
  101.                  */  
  102.                 if (hasMore && (lastVisibleItem >= totalItemCount - 1)  
  103.                         && !isLoadMore) {  
  104.                     isLoadMore = true;  
  105.                     loadMore();  
  106.                 }  
  107.   
  108.             }  
  109.         };  
  110.   
  111.         /** 
  112.          * 下拉至顶部刷新监听 
  113.          */  
  114.         mRefreshListener = new OnRefreshListener() {  
  115.   
  116.             @Override  
  117.             public void onRefresh() {  
  118.                 if (!isRefresh) {  
  119.                     isRefresh = true;  
  120.                     refresh();  
  121.                 }  
  122.             }  
  123.         };  
  124.         swipeRfl.setOnRefreshListener(mRefreshListener);  
  125.         recyclerView.setHasFixedSize(true);  
  126.         layoutManager = new LinearLayoutManager(context);  
  127.         layoutManager.setOrientation(LinearLayoutManager.VERTICAL);  
  128.         recyclerView.setLayoutManager(layoutManager);  
  129.         recyclerView.setOnScrollListener(mScrollListener);  
  130.     }  
  131.   
  132.     public void setOrientation(int orientation) {  
  133.         if (orientation != 0 && orientation != 1) {  
  134.             layoutManager.setOrientation(VERTICAL);  
  135.         } else {  
  136.             layoutManager.setOrientation(HORIZONTAL);  
  137.         }  
  138.     }  
  139.   
  140.     public int getOrientation() {  
  141.         return layoutManager.getOrientation();  
  142.     }  
  143.   
  144.     public void setPullLoadMoreEnable(boolean enable) {  
  145.         this.hasMore = enable;  
  146.     }  
  147.   
  148.     public boolean getPullLoadMoreEnable() {  
  149.         return hasMore;  
  150.     }  
  151.   
  152.     public void setPullRefreshEnable(boolean enable) {  
  153.         swipeRfl.setEnabled(enable);  
  154.     }  
  155.   
  156.     public boolean getPullRefreshEnable() {  
  157.         return swipeRfl.isEnabled();  
  158.     }  
  159.   
  160.     public void setLoadMoreListener() {  
  161.         recyclerView.setOnScrollListener(mScrollListener);  
  162.     }  
  163.   
  164.     public void loadMore() {  
  165.         if (mRefreshLoadMoreListner != null && hasMore) {  
  166.             mRefreshLoadMoreListner.onLoadMore();  
  167.               
  168.         }  
  169.     }  
  170.   
  171.     /** 
  172.      * 加载更多完毕,为防止频繁网络请求,isLoadMore为false才可再次请求更多数据 
  173.      */  
  174.     public void setLoadMoreCompleted(){  
  175.         isLoadMore = false;  
  176.     }  
  177.       
  178.     public void stopRefresh() {  
  179.         isRefresh = false;  
  180.         swipeRfl.setRefreshing(false);  
  181.     }  
  182.   
  183.     public void setRefreshLoadMoreListener(RefreshLoadMoreListener listener) {  
  184.         mRefreshLoadMoreListner = listener;  
  185.     }  
  186.   
  187.     public void refresh() {  
  188.         if (mRefreshLoadMoreListner != null) {  
  189.             mRefreshLoadMoreListner.onRefresh();  
  190.         }  
  191.     }  
  192.   
  193.     public void setAdapter(RecyclerView.Adapter adapter) {  
  194.         if (adapter != null)  
  195.             recyclerView.setAdapter(adapter);  
  196.     }  
  197.   
  198.     public interface RefreshLoadMoreListener {  
  199.         public void onRefresh();  
  200.   
  201.         public void onLoadMore();  
  202.     }  
  203. }  

3.那么我们来看看如何使用

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. package com.example.pulltorefreshrecyeclerviewdemo;  
  2.   
  3. import java.util.ArrayList;  
  4. import org.json.JSONArray;  
  5. import org.json.JSONException;  
  6. import org.json.JSONObject;  
  7. import android.app.Activity;  
  8. import android.os.Bundle;  
  9. import android.view.Menu;  
  10. import android.view.MenuItem;  
  11. import android.widget.LinearLayout;  
  12. import com.jabony.recyclerpulltorefresh.PullRefreshRecyclerView;  
  13.   
  14. /** 
  15.  *  
  16.  * @author jabony 
  17.  * @since 2015年3月31日 16:08:56 
  18.  */  
  19. public class MainActivity extends Activity implements  
  20.         PullRefreshRecyclerView.RefreshLoadMoreListener {  
  21.     private PullRefreshRecyclerView prrv;  
  22.     private ActivityAdapter allActAdapter;  
  23.     private JSONObject response = null;  
  24.     private int page = 0;  
  25.     /** 
  26.      * 全部活动数据源 
  27.      */  
  28.     private ArrayList<ActivityBean> actAllList = new ArrayList<ActivityBean>();  
  29.     private String jsonStr = "{\"datas\":{\"count\":\"6\",\"list\":[{\"id\":\"311\",\"end_date\":\"1437235200\",\"shopid\":\"387\",\"subject\":\"金鹏会员里程百日冲刺,最高可获35000里程奖励\",\"is_collected\":\"2\",img:\"http://jfgj.wadiankeji.com/Uploads/2015-03-26/5513bd4120d64.jpg\",\"collec_num\":\"1\",\"start_date\":\"1428681600\",\"url\":\"http://jfgj.wadiankeji.com/api/html/detail/actid/311\"},{\"id\":\"302\",\"end_date\":\"1437235200\",\"shopid\":\"387\",\"subject\":\"金鹏会员里程百日冲刺,最高可获35000里程奖励\",\"is_collected\":\"2\",img:\"http://jfgj.wadiankeji.com/Uploads/2015-03-26/5513bd4120d64.jpg\",\"collec_num\":\"1\",\"start_date\":\"1428681600\",\"url\":\"http://jfgj.wadiankeji.com/api/html/detail/actid/311\"},{\"id\":\"311\",\"end_date\":\"1437235200\",\"shopid\":\"387\",\"subject\":\"金鹏会员里程百日冲刺,最高可获35000里程奖励\",\"is_collected\":\"2\",img:\"http://jfgj.wadiankeji.com/Uploads/2015-03-26/5513bd4120d64.jpg\",\"collec_num\":\"1\",\"start_date\":\"1428681600\",\"url\":\"http://jfgj.wadiankeji.com/api/html/detail/actid/311\"},{\"id\":\"311\",\"end_date\":\"1437235200\",\"shopid\":\"387\",\"subject\":\"金鹏会员里程百日冲刺,最高可获35000里程奖励\",\"is_collected\":\"2\",img:\"http://jfgj.wadiankeji.com/Uploads/2015-03-26/5513bd4120d64.jpg\",\"collec_num\":\"1\",\"start_date\":\"1428681600\",\"url\":\"http://jfgj.wadiankeji.com/api/html/detail/actid/311\"},{\"id\":\"311\",\"end_date\":\"1437235200\",\"shopid\":\"387\",\"subject\":\"金鹏会员里程百日冲刺,最高可获35000里程奖励\",\"is_collected\":\"2\",img:\"http://jfgj.wadiankeji.com/Uploads/2015-03-26/5513bd4120d64.jpg\",\"collec_num\":\"1\",\"start_date\":\"1428681600\",\"url\":\"http://jfgj.wadiankeji.com/api/html/detail/actid/311\"},{\"id\":\"311\",\"end_date\":\"1437235200\",\"shopid\":\"387\",\"subject\":\"金鹏会员里程百日冲刺,最高可获35000里程奖励\",\"is_collected\":\"2\",img:\"http://jfgj.wadiankeji.com/Uploads/2015-03-26/5513bd4120d64.jpg\",\"collec_num\":\"1\",\"start_date\":\"1428681600\",\"url\":\"http://jfgj.wadiankeji.com/api/html/detail/actid/311\"}]},\"status\":\"10000\",\"msg\":\"faxian\"}";  
  30.   
  31.     @Override  
  32.     protected void onCreate(Bundle savedInstanceState) {  
  33.         super.onCreate(savedInstanceState);  
  34.         setContentView(R.layout.activity_main);  
  35.         /** 
  36.          * 绑定组合控件 
  37.          */  
  38.         prrv = (PullRefreshRecyclerView) findViewById(R.id.prrv);  
  39.         /** 
  40.          * 初始化适配器 
  41.          */  
  42.         allActAdapter = new ActivityAdapter(actAllList, MainActivity.this);  
  43.         /** 
  44.          * 下拉上拉加载更多监听 
  45.          */  
  46.         prrv.setRefreshLoadMoreListener(this);  
  47.         /** 
  48.          * 禁用刷新 
  49.          */  
  50.         // prrv.setPullRefreshEnable(false);  
  51.         /** 
  52.          * 禁用加载更多 
  53.          */  
  54.         // prrv.setPullLoadMoreEnable(false);  
  55.   
  56.         /** 
  57.          * 设置布局方向 
  58.          */  
  59.         prrv.setVertical();  
  60.   
  61.         /** 
  62.          * 设置适配器 
  63.          */  
  64.         prrv.setAdapter(allActAdapter);  
  65.         /** 
  66.          * 首次进入刷新 
  67.          */  
  68.         prrv.refresh();  
  69.     }  
  70.   
  71.     /** 
  72.      * 加载分页数据 
  73.      */  
  74.     public void loadNetDatas(int currentPage) {  
  75.         if (currentPage > 2) {  
  76.             prrv.setPullLoadMoreEnable(false);  
  77.             return;  
  78.         }  
  79.         try {  
  80.             response = new JSONObject(jsonStr);  
  81.             String msg = null;  
  82.             int count = 0;  
  83.             int status = 0;  
  84.             if (!response.isNull("datas")) {  
  85.                 JSONObject dataObj = response.getJSONObject("datas");  
  86.   
  87.                 if (!dataObj.isNull("count")) {  
  88.                     count = dataObj.getInt("count");  
  89.                 }  
  90.   
  91.                 if (!dataObj.isNull("list")) {  
  92.                     JSONArray listArray = dataObj.getJSONArray("list");  
  93.                     int size = listArray.length();  
  94.                     for (int i = 0; i < size; i++) {  
  95.   
  96.                         JSONObject obj = listArray.getJSONObject(i);  
  97.                         ActivityBean ab = new ActivityBean();  
  98.                         if (!obj.isNull("id")) {  
  99.                             ab.setActId(obj.getString("id"));  
  100.                         }  
  101.                         if (!obj.isNull("shopid")) {  
  102.                             ab.setShopId(obj.getString("shopid"));  
  103.                         }  
  104.                         if (!obj.isNull("is_top")) {  
  105.                             if ("1".equals(obj.getString("is_top"))) {  
  106.                                 ab.setTop(true);  
  107.                             }  
  108.   
  109.                         }  
  110.   
  111.                         if (!obj.isNull("img")) {  
  112.                             ab.setImgUrl(obj.getString("img"));  
  113.                         }  
  114.                         if (!obj.isNull("subject")) {  
  115.                             ab.setActTitile(obj.getString("subject"));  
  116.                         }  
  117.                         if (!obj.isNull("start_date")) {  
  118.                             if (obj.getString("start_date") != null  
  119.                                     && !"".equals(obj.getString("start_date"))) {  
  120.                                 ab.setStartDate(obj.getLong("start_date"));  
  121.                             }  
  122.   
  123.                         }  
  124.                         if (!obj.isNull("end_date")) {  
  125.                             if (obj.getString("end_date") != null  
  126.                                     && !"".equals(obj.getString("end_date"))) {  
  127.                                 ab.setEndDate(obj.getLong("end_date"));  
  128.                             }  
  129.   
  130.                         }  
  131.                         if (!obj.isNull("collec_num")) {  
  132.                             String collcNum = obj.getString("collec_num");  
  133.                             if (collcNum == null || "".equals(collcNum)) {  
  134.                                 ab.setCollectNum(0);  
  135.                             } else {  
  136.                                 ab.setCollectNum(obj.getInt("collec_num"));  
  137.                             }  
  138.                             collcNum = null;  
  139.                         }  
  140.                         if (!obj.isNull("is_collected")) {  
  141.                             ab.setCollected(obj.getInt("is_collected") == 1 ? true  
  142.                                     : false);  
  143.                         }  
  144.                         if (!obj.isNull("url")) {  
  145.                             ab.setUrl(obj.getString("url"));  
  146.                         }  
  147.                         actAllList.add(ab);  
  148.                         /** 
  149.                          * 刷新适配器 
  150.                          */  
  151.                         allActAdapter.notifyDataSetChanged();  
  152.                         /** 
  153.                          * 如果刷新则停止刷新 
  154.                          */  
  155.                         prrv.stopRefresh();  
  156.                         /** 
  157.                          * 加载更多完毕 
  158.                          */  
  159.                         prrv.setLoadMoreCompleted();  
  160.                         /** 
  161.                          * 如果没有更多数据则设置不可加载更多 
  162.                          */  
  163.                         // prrv.setPullLoadMoreEnable(false);  
  164.                     }  
  165.                 }  
  166.             }  
  167.         } catch (JSONException e) {  
  168.             // TODO Auto-generated catch block  
  169.             e.printStackTrace();  
  170.         }  
  171.     }  
  172.   
  173.     @Override  
  174.     public void onRefresh() {  
  175.         // TODO Auto-generated method stub  
  176.         prrv.setPullRefreshEnable(true);  
  177.         prrv.setPullLoadMoreEnable(true);  
  178.         actAllList.clear();  
  179.         page = 1;  
  180.         loadNetDatas(page);  
  181.     }  
  182.   
  183.     @Override  
  184.     public void onLoadMore() {  
  185.         // TODO Auto-generated method stub  
  186.         page++;  
  187.         loadNetDatas(page);  
  188.     }  
  189.   
  190.     @Override  
  191.     public boolean onCreateOptionsMenu(Menu menu) {  
  192.         // Inflate the menu; this adds items to the action bar if it is present.  
  193.         getMenuInflater().inflate(R.menu.main, menu);  
  194.         return true;  
  195.     }  
  196.   
  197.     @Override  
  198.     public boolean onOptionsItemSelected(MenuItem item) {  
  199.         // Handle action bar item clicks here. The action bar will  
  200.         // automatically handle clicks on the Home/Up button, so long  
  201.         // as you specify a parent activity in AndroidManifest.xml.  
  202.         int id = item.getItemId();  
  203.         if (id == R.id.action_delete) {  
  204.             actAllList.clear();  
  205.             allActAdapter.notifyDataSetChanged();  
  206.             page = 1;  
  207.             prrv.customExceptView(R.drawable.no_data, "这里空空如也");  
  208.             return true;  
  209.         }  
  210.         if (id == R.id.action_orintation) {  
  211.             int orientation = prrv.getOrientation();  
  212.             if (orientation == LinearLayout.HORIZONTAL) {  
  213.                 prrv.setVertical();  
  214.             } else {  
  215.                 prrv.setHorizontal();  
  216.             }  
  217.             return true;  
  218.         }  
  219.         if (id == R.id.action_refreshable) {  
  220.             if (prrv.getPullRefreshEnable()) {  
  221.                 prrv.setPullRefreshEnable(!prrv.getPullRefreshEnable());  
  222.             } else {  
  223.                 prrv.setPullRefreshEnable(!prrv.getPullRefreshEnable());  
  224.             }  
  225.             return true;  
  226.         }  
  227.         if (id == R.id.action_loadmoreable) {  
  228.             if (prrv.getPullLoadMoreEnable()) {  
  229.                 prrv.setPullLoadMoreEnable(!prrv.getPullLoadMoreEnable());  
  230.             } else {  
  231.                 prrv.setPullLoadMoreEnable(!prrv.getPullLoadMoreEnable());  
  232.             }  
  233.             return true;  
  234.         }  
  235.         if (id == R.id.action_stoprefresh) {  
  236.             prrv.stopRefresh();  
  237.             return true;  
  238.         }  
  239.         if (id == R.id.action_scrollToTop) {  
  240.             prrv.scrollToTop();  
  241.             return true;  
  242.         }  
  243.         return super.onOptionsItemSelected(item);  
  244.     }  
  245. }  


4.看上去已经搞定了,但你会发现需要引入一个库项目没错RecyclerView的库项目

这都好办,我们考虑的重点不在这里,这样就完美了吗?我们在使用的时候在布局中这么写,看是没有什么

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical"  
  6.     tools:context="com.jabony.recyclerpulltorefresh.MainActivity" >  
  7.     <com.jabony.recyclerpulltorefresh.PullRefreshRecyclerView  
  8.         android:id="@+id/prrv"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="match_parent" />  
  11.   
  12. </LinearLayout>  

5.我们能不能把自定义的View布局省掉?

答案当然是肯定的:我们来做个小实验在原来采用

// 导入布局
LayoutInflater.from(context).inflate(R.layout.pulltorefreshrecyclerview, this, true);

在老的方式做下调整,完全脱离布局,代码写布局

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. LinearLayout rootLl = new LinearLayout(context);  
  2. rootLl.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,  
  3.         LayoutParams.MATCH_PARENT));  
  4. <span style="color:#ff0000;">mExceptView = initExceptionView(context);//异常布局</span>  
  5. mExceptView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,  
  6.         LayoutParams.MATCH_PARENT));  
  7. mExceptView.setVisibility(View.GONE);  
  8. swipeRfl = new SwipeRefreshLayout(context);  
  9. swipeRfl.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,  
  10.         LayoutParams.MATCH_PARENT));  
  11. FrameLayout bootLl = new FrameLayout(context);  
  12. bootLl.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,  
  13.         LayoutParams.WRAP_CONTENT));  
  14. recyclerView = new RecyclerView(context);  
  15. recyclerView.setVerticalScrollBarEnabled(true);  
  16. recyclerView.setHorizontalScrollBarEnabled(true);  
  17. recyclerView.setLayoutParams(new LayoutParams(  
  18.         LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));  
  19. bootLl.addView(recyclerView);  
  20. bootLl.addView(mExceptView);  
  21. swipeRfl.addView(bootLl);  
  22. rootLl.addView(swipeRfl);  
  23. this.addView(rootLl);  
这样就把需要有xml布局引入的布局改动为纯代码的,虽然不怎么完美,但是测试使用是没有问题了。

6.没错我引入了异常布局,为了交互友好,允许用户半自定义异常界面


也就是其实布局什么样子 我早就定好了,你只需要按照方法传图片的id和提示的字符串,你一定会好奇到底是什么样子的,马上贴图。

那么刷新呢,非常简单,点击图片可以刷新操作,这样就看似比较完善了。


7.总结一下:

PulltoRefreshRecyclerView是在SwipeRefreshLayout和RecyclerView的基础上组合改造的。

需要实现OnRefreshListener的方法

可以控制能否刷新,能否加在更多

可以控制显示的方向

提供回到Top的方法

停止刷新效果

可以半定义异常界面的效果


下载地址:

自定义组合下拉刷新上拉加载更多控件

0 0