安卓开发笔记——关于开源组件PullToRefresh实现下拉刷新和上拉加载(一分钟搞定,超级简单)
前言
以前在实现ListView下拉刷新和上拉加载数据的时候都是去继承原生的ListView重写它的一些方法,实现起来非常繁杂,需要我们自己去给ListView定制下拉刷新和上拉加载的布局文件,然后添加ScrollView和OnTouch监听,设置回调接口获取数据,为了更好的交互体验,我们还不能直接利用setVisibility隐藏显示布局等等一大堆的操作,累都累死了。(题外话:关于下拉刷新在新版的android-support-v4.jar里,其实谷歌已经为我们提供了一个控件叫SwipeRefreshLayout,使用方法也非常简单,有兴趣的朋友可以自己网上了解下)它的实现效果大致是这样的:

今天来说下关于开源项目PullToRefresh的使用方法,轻轻松松几行代码就可以把下拉刷新和上拉加载功能给实现了。(开源的东西虽然好用,但作为学习,还是建议大家先不用开源组件自己去实现一遍所需要的效果,毕竟原理需要懂),好了,言归正传,我尽量的言简意赅,进入主题。
先看下最后的实现效果图:

准备工作
1、既然是利用PullToRefresh组件来实现下拉刷新和上拉加载数据的效果,那么首先我们需要先把它下载下来。
这是PullToRefresh在GitHub上的下载地址:https://github.com/chrisbanes/Android-PullToRefresh/wiki/Quick-Start-Guide
很简单,下载完毕后我们就可以开始进入开发工作了。
磨刀不误砍柴工
1、首先先导入该项目

在导入项目后,我们会发现出现了很多红叉,不用担心,这个只是引用库路径出错罢了,我们右键点击有红叉的文件选择Properties,选择Andorid下拉,把对应的library重新 引入即可,依样画葫芦,其他出现的红叉的文件也都这样做。

把红叉都解决完之后,有个很重要的事情要做,把刚导入的所有文件夹里的android-support-v4.jar和你自己的项目里的v4包统一了,避免v4包版本不一致导致项目运行出错。

干活干活!
布局文件,非常简单,只放了一个可下拉刷新的ListView
1 <RelativeLayout 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 6 <com.handmark.pulltorefresh.library.PullToRefreshListView 7 android:id="@+id/mylistview" 8 android:layout_width="match_parent" 9 android:layout_height="match_parent" 10 > 11 </com.handmark.pulltorefresh.library.PullToRefreshListView> 12 13 </RelativeLayout>
主代码文件:
1 package com.rabbit.pulltorefreshdemo;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import android.app.Activity;
7 import android.os.AsyncTask;
8 import android.os.Bundle;
9 import android.widget.ArrayAdapter;
10 import android.widget.ListView;
11
12 import com.handmark.pulltorefresh.library.PullToRefreshBase;
13 import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode;
14 import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
15 import com.handmark.pulltorefresh.library.PullToRefreshListView;
16
17 public class MainActivity extends Activity {
18
19 //声明下拉刷新ListView组件
20 private PullToRefreshListView myListView;
21 //声明数据源
22 private List<String> data;
23 //声明适配器
24 private ArrayAdapter<String> adapter;
25
26 @Override
27 protected void onCreate(Bundle savedInstanceState) {
28 super.onCreate(savedInstanceState);
29 setContentView(R.layout.activity_main);
30 //获取下拉刷新ListView组件
31 this.myListView=(PullToRefreshListView) findViewById(R.id.mylistview);
32 //模拟数据
33 this.data=new ArrayList<String>();
34 data.add("JAVA");
35 data.add("PHP");
36 data.add("C++");
37 data.add("C#");
38 //实例化Adapter
39 this.adapter=new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, data);
40 //设置Adapter
41 myListView.setAdapter(adapter);
42 //设置支持上下拉动和监听
43 myListView.setMode(Mode.BOTH);
44 myListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
45
46 @Override
47 public void onRefresh(PullToRefreshBase<ListView> refreshView) {
48
49 if(refreshView.isShownHeader()){
50 //判断头布局是否可见,如果可见执行下拉刷新
51 //设置尾布局样式文字
52 myListView.getLoadingLayoutProxy().setRefreshingLabel("正在刷新");
53 myListView.getLoadingLayoutProxy().setPullLabel("下拉刷新数据");
54 myListView.getLoadingLayoutProxy().setReleaseLabel("释放开始刷新");
55 //模拟加载数据线程休息3秒
56 new AsyncTask<Void, Void, Void>() {
57 @Override
58 protected Void doInBackground(Void... params) {
59 try {
60 Thread.sleep(3000);
61 data.add("刷新数据1");
62 data.add("刷新数据2");
63 data.add("刷新数据3");
64 } catch (InterruptedException e) {
65 e.printStackTrace();
66 }
67 return null;
68 }
69
70 @Override
71 protected void onPostExecute(Void result) {
72 super.onPostExecute(result);
73 //完成对下拉刷新ListView的更新操作
74 adapter.notifyDataSetChanged();
75 //将下拉视图收起
76 myListView.onRefreshComplete();
77 }
78 }.execute();
79 }
80 if(refreshView.isShownFooter()){
81 //判断尾布局是否可见,如果可见执行上拉加载更多
82 //设置尾布局样式文字
83 myListView.getLoadingLayoutProxy().setRefreshingLabel("正在加载");
84 myListView.getLoadingLayoutProxy().setPullLabel("上拉加载更多");
85 myListView.getLoadingLayoutProxy().setReleaseLabel("释放开始加载");
86 //模拟加载数据线程休息3秒
87 new AsyncTask<Void, Void, Void>() {
88 @Override
89 protected Void doInBackground(Void... params) {
90 try {
91 Thread.sleep(3000);
92 data.add("更多数据1");
93 data.add("更多数据2");
94 data.add("更多数据3");
95 } catch (InterruptedException e) {
96 e.printStackTrace();
97 }
98 return null;
99 }
100
101 @Override
102 protected void onPostExecute(Void result) {
103 super.onPostExecute(result);
104 //完成对下拉刷新ListView的更新操作
105 adapter.notifyDataSetChanged();
106 //将下拉视图收起
107 myListView.onRefreshComplete();
108 }
109 }.execute();
110
111
112 }
113
114 }
115 });
116
117 }
118
119
120 }
其实和普通ListView的使用方式差不多,只是多了一些属性的设置,这里有几个要注意的地方:
1、模式的设置,默认下PullToRefresh的刷新模式只支持下拉刷新,我们可以通过setMode(Mode.XXXX)来设置它
1 BOTH:上拉刷新和下拉刷新都支持 2 DISABLED:禁用上拉下拉刷新 3 PULL_FROM_START:仅支持下拉刷新(默认) 4 PULL_FROM_END:仅支持上拉刷新 5 MANUAL_REFRESH_ONLY:只允许手动触发
2、补充上述描述第1点,当我们设置模式为BOTH的时候,我们就可以实现下拉和上拉了,但这里的它们的样式是一样的,我们需要的场景应该是下拉的时候显示"下拉刷新数据,正在刷新数据,数据刷新成功....",而在我们上拉的时候应该出现的场景是"上拉加载数据,正在加载数据,加载数据成功...",所以这里我们需要对样式进行设置。
由于PullToRefresh默认是没给我们判断到底是上拉还是下拉的方法,所以我们需要去源代码里修改下它的代码,Ctrl+Shift+T搜索下PullToRefreshBase类,打开后再后最后面我们补上这样一段代码,我们可以根据当头布局可见的时候执行下拉刷新,当尾布局可见的时候执行下拉加载,这样我们就可以根据头尾布局来判断用户到底是执行上拉还是下拉操作了。
1 //判别头部是否展示出来,如果展示出来代表下拉使得头部展示。true为下拉
2 public boolean isShownHeader() {
3 return getHeaderLayout().isShown();
4 }
5 //判别低部是否展示出来,如果展示出来代表上拉使得低部展示。true为上拉
6 public boolean isShownFooter() {
7 return getFooterLayout().isShown();
8 }
3、这是关于PullToRefresh的一些属性设置,在源码中可以找到,这里我做了下翻译:
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <declare-styleable name="PullToRefresh"> 4 <!-- A drawable to use as the background of the Refreshable View --> 5 <!-- 设置整个刷新列表的背景色 --> 6 <attr name="ptrRefreshableViewBackground" format="reference|color" /> 7 <!-- A drawable to use as the background of the Header and Footer Loading Views --> 8 <!-- 设置下拉Header或者上拉Footer的背景色 --> 9 <attr name="ptrHeaderBackground" format="reference|color" /> 10 <!-- Text Color of the Header and Footer Loading Views --> 11 <!-- 用于设置Header与Footer中文本的颜色 --> 12 <attr name="ptrHeaderTextColor" format="reference|color" /> 13 <!-- Text Color of the Header and Footer Loading Views Sub Header --> 14 <!-- 用于设置Header与Footer中上次刷新时间的颜色 --> 15 <attr name="ptrHeaderSubTextColor" format="reference|color" /> 16 <!-- Mode of Pull-to-Refresh that should be used --> 17 <attr name="ptrMode"> 18 <flag name="disabled" value="0x0" /><!-- 禁用下拉刷新 --> 19 <flag name="pullFromStart" value="0x1" /><!-- 仅支持下拉刷新 --> 20 <flag name="pullFromEnd" value="0x2" /><!-- 仅支持上拉刷新 --> 21 <flag name="both" value="0x3" /><!-- 上拉刷新和下拉刷新都支持 --> 22 <flag name="manualOnly" value="0x4" /><!-- 只允许手动触发 --> 23 24 <!-- These last two are depreacted --> 25 <flag name="pullDownFromTop" value="0x1" /> 26 <flag name="pullUpFromBottom" value="0x2" /> 27 </attr> 28 <!-- Whether the Indicator overlay(s) should be used --> 29 <!-- 如果为true会在mPullRefreshListView中出现icon,右上角和右下角,挺有意思的 --> 30 <attr name="ptrShowIndicator" format="reference|boolean" /> 31 <!-- Drawable to use as Loading Indicator. Changes both Header and Footer. --> 32 <!-- 同时改变头部和底部的图标 --> 33 <attr name="ptrDrawable" format="reference" /> 34 <!-- Drawable to use as Loading Indicator in the Header View. Overrides value set in ptrDrawable. --> 35 <!-- 头部视图的图标--> 36 <attr name="ptrDrawableStart" format="reference" /> 37 38 <!-- Drawable to use as Loading Indicator in the Footer View. Overrides value set in ptrDrawable. --> 39 <!-- 底部视图的图标 --> 40 <attr name="ptrDrawableEnd" format="reference" /> 41 <!-- Whether Android's built-in Over Scroll should be utilised for Pull-to-Refresh. --> 42 <attr name="ptrOverScroll" format="reference|boolean" /> 43 <!-- Base text color, typeface, size, and style for Header and Footer Loading Views --> 44 <!-- 分别设置拉Header或者上拉Footer中字体的类型颜色等等 --> 45 <attr name="ptrHeaderTextAppearance" format="reference" /> 46 <!-- Base text color, typeface, size, and style for Header and Footer Loading Views Sub Header --> 47 <attr name="ptrSubHeaderTextAppearance" format="reference" /> 48 <!-- Style of Animation should be used displayed when pulling. --> 49 <attr name="ptrAnimationStyle"> 50 <flag name="rotate" value="0x0" /><!-- flip(翻转动画), rotate(旋转动画) --> 51 <flag name="flip" value="0x1" /> 52 </attr> 53 <!-- Whether the user can scroll while the View is Refreshing --> 54 <!-- 刷新的时候,是否允许ListView或GridView滚动 --> 55 <attr name="ptrScrollingWhileRefreshingEnabled" format="reference|boolean" /> 56 <!-- 57 Whether PullToRefreshListView has it's extras enabled. This allows the user to be 58 able to scroll while refreshing, and behaves better. It acheives this by adding 59 Header and/or Footer Views to the ListView. 60 --> 61 <!-- 决定了Header,Footer以何种方式加入mPullRefreshListView,true为headView方式加入,就是滚动时刷新头部会一起滚动 --> 62 <attr name="ptrListViewExtrasEnabled" format="reference|boolean" /> 63 <!-- 64 Whether the Drawable should be continually rotated as you pull. This only 65 takes effect when using the 'Rotate' Animation Style. 66 --> 67 <attr name="ptrRotateDrawableWhilePulling" format="reference|boolean" /> 68 <!-- BELOW HERE ARE DEPRECEATED. DO NOT USE. --> 69 <attr name="ptrAdapterViewBackground" format="reference|color" /> 70 <attr name="ptrDrawableTop" format="reference" /> 71 <attr name="ptrDrawableBottom" format="reference" /> 72 </declare-styleable> 73 </resources>
设置属性也很简单,在对应的布局文件里直接设置就可以,比如字体颜色:
1 <com.handmark.pulltorefresh.library.PullToRefreshListView 2 xmlns:ptr="http://schemas.android.com/apk/res-auto" 3 android:id="@+id/lv_friendsline" 4 android:layout_width="fill_parent" 5 android:layout_height="fill_parent" 6 ptr:ptrHeaderTextColor="#000000" 7 >
其他的一些,大家看我代码注释吧,写的非常详细了。
补充:关于这个PullToRefresh它不仅仅支持ListView,比如ScrollView,GridView等等,只要是能滚动到控件它都通吃,具体使用方法大家可以参考我们一开始导入的项目里的LauncherActivity。


浙公网安备 33010602011771号