安卓開發筆記——關於開源組件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。

 

 

作者:Balla_兔子
出處:http://www.cnblogs.com/lichenwei/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,日后必有一番作為!旁邊有“推薦”二字,你就順手把它點了吧,相得准,我分文不收;相不准,你也好回來找我!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM