移動(dòng)端開發(fā)矢棚,不聯(lián)網(wǎng)的App少之又少,所以下拉刷新數(shù)據(jù)府喳、上拉加載更多數(shù)據(jù)作為一個(gè)基礎(chǔ)功能蒲肋,相關(guān)的庫層出不窮,這里就記錄一下曾經(jīng)用過的庫吧钝满,希望對大家有用兜粘。
一、 Android-PullToRefresh
這是最經(jīng)典的下拉刷新庫了弯蚜。在github上有6952個(gè)Star孔轴、4746個(gè)Fork。在用eclipse開發(fā)Android的時(shí)代碎捺,是必備使用的庫之一路鹰。
集成方式也很簡單。
- eclipse導(dǎo)入lib 源碼
- 顯示代碼:
<!--
The PullToRefreshListView replaces a standard ListView widget.
The ID CAN NOT be @+id/android:list
-->
<com.handmark.pulltorefresh.library.PullToRefreshListView
android:id="@+id/pull_to_refresh_listview"
android:layout_height="fill_parent"
android:layout_width="fill_parent" />
- 控制代碼:
// Set a listener to be invoked when the list should be refreshed.
PullToRefreshListView pullToRefreshView = (PullToRefreshListView) findViewById(R.id.pull_to_refresh_listview);
pullToRefreshView.setOnRefreshListener(new OnRefreshListener<ListView>() {
@Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
// Do work to refresh the list here.
new GetDataTask().execute();
}
});
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
...
@Override
protected void onPostExecute(String[] result) {
// Call onRefreshComplete when the list has been refreshed.
pullToRefreshView.onRefreshComplete();
super.onPostExecute(result);
}
}
遺憾的是收厨,這個(gè)項(xiàng)目不再維護(hù)晋柱,最后一次更新日期為2013年2月2號(hào),在Android開發(fā)已經(jīng)進(jìn)化到gradle一行導(dǎo)包的時(shí)代诵叁,只能放棄它了雁竞。
二、android-Ultra-Pull-To-Refresh
這是國內(nèi)Android開發(fā)大神廖祜秋開發(fā)的一個(gè)開源庫拧额。特點(diǎn)是內(nèi)置各種下拉刷新交互風(fēng)格碑诉。
-
下拉刷新(iOS風(fēng)格)
<div>
-
釋放刷新(經(jīng)典風(fēng)格)
<div>
-
刷新時(shí),頭部保持(新浪微博)
-
刷新時(shí)势腮,頭部不保持(微信朋友圈)
-
自動(dòng)刷新联贩,進(jìn)入界面時(shí)自動(dòng)刷新
</div>
集成方式很簡單:
- 一行導(dǎo)包
compile 'in.srain.cube:ultra-ptr:1.0.11'
- 界面邏輯:
<in.srain.cube.views.ptr.PtrFrameLayout
android:id="@+id/store_house_ptr_frame"
xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
cube_ptr:ptr_resistance="1.7"
cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
cube_ptr:ptr_duration_to_close="300"
cube_ptr:ptr_duration_to_close_header="2000"
cube_ptr:ptr_keep_header_when_refresh="true"
cube_ptr:ptr_pull_to_fresh="false" >
<LinearLayout
android:id="@+id/store_house_ptr_image_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/cube_mints_333333"
android:clickable="true"
android:padding="10dp">
<in.srain.cube.image.CubeImageView
android:id="@+id/store_house_ptr_image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</in.srain.cube.views.ptr.PtrFrameLayout>
- 控制邏輯:
ptrFrame.setPtrHandler(new PtrHandler() {
@Override
public void onRefreshBegin(PtrFrameLayout frame) {
frame.postDelayed(new Runnable() {
@Override
public void run() {
ptrFrame.refreshComplete();
}
}, 1800);
}
@Override
public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
// 默認(rèn)實(shí)現(xiàn),根據(jù)實(shí)際情況做改動(dòng)
return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);
}
});
相關(guān)原理可以參考作者寫的文檔——我眼中的下拉刷新
遺憾的是這個(gè)庫不支持上拉加載更多捎拯,作者有提供一個(gè)解決方案——android-cube-app泪幌,但是這個(gè)解決方案是一個(gè)demo盲厌,而不是內(nèi)嵌在Ultra-Pull-To-Refresh中,不符合一行導(dǎo)包的原則了祸泪。
三吗浩、BGARefreshLayout-Android
這個(gè)庫同時(shí)支持下拉刷新和上拉加載更多,集成也很簡單:
- 一行導(dǎo)包
dependencies {
compile 'com.android.support:recyclerview-v7:latestVersion'
// 記得添加nineoldandroids
compile 'com.nineoldandroids:library:2.4.0'
compile 'cn.bingoogolapple:bga-refreshlayout:latestVersion@aar'
}
- 界面邏輯:
<cn.bingoogolapple.refreshlayout.BGARefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl_modulename_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 內(nèi)容控件 -->
<AnyView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</cn.bingoogolapple.refreshlayout.BGARefreshLayout>
- 控制邏輯:
// 讓activity或者fragment實(shí)現(xiàn)BGARefreshLayoutDelegate接口
public class ModuleNameActivity extends AppCompatActivity implements BGARefreshLayout.BGARefreshLayoutDelegate {
private BGARefreshLayout mRefreshLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_moudlename);
initRefreshLayout();
}
private void initRefreshLayout(BGARefreshLayout refreshLayout) {
mRefreshLayout = (BGARefreshLayout) findViewById(R.id.rl_modulename_refresh);
// 為BGARefreshLayout設(shè)置代理
mRefreshLayout.setDelegate(this);
// 設(shè)置下拉刷新和上拉加載更多的風(fēng)格 參數(shù)1:應(yīng)用程序上下文没隘,參數(shù)2:是否具有上拉加載更多功能
BGARefreshViewHolder refreshViewHolder = new XXXImplRefreshViewHolder(this, true))
// 設(shè)置下拉刷新和上拉加載更多的風(fēng)格
mRefreshLayout.setRefreshViewHolder(refreshViewHolder);
// 為了增加下拉刷新頭部和加載更多的通用性懂扼,提供了以下可選配置選項(xiàng) -------------START
// 設(shè)置正在加載更多時(shí)不顯示加載更多控件
// mRefreshLayout.setIsShowLoadingMoreView(false);
// 設(shè)置正在加載更多時(shí)的文本
refreshViewHolder.setLoadingMoreText(loadingMoreText);
// 設(shè)置整個(gè)加載更多控件的背景顏色資源id
refreshViewHolder.setLoadMoreBackgroundColorRes(loadMoreBackgroundColorRes);
// 設(shè)置整個(gè)加載更多控件的背景drawable資源id
refreshViewHolder.setLoadMoreBackgroundDrawableRes(loadMoreBackgroundDrawableRes);
// 設(shè)置下拉刷新控件的背景顏色資源id
refreshViewHolder.setRefreshViewBackgroundColorRes(refreshViewBackgroundColorRes);
// 設(shè)置下拉刷新控件的背景drawable資源id
refreshViewHolder.setRefreshViewBackgroundDrawableRes(refreshViewBackgroundDrawableRes);
// 設(shè)置自定義頭部視圖(也可以不用設(shè)置) 參數(shù)1:自定義頭部視圖(例如廣告位), 參數(shù)2:上拉加載更多是否可用
mRefreshLayout.setCustomHeaderView(mBanner, false);
// 可選配置 -------------END
}
@Override
public void onBGARefreshLayoutBeginRefreshing(BGARefreshLayout refreshLayout) {
// 在這里加載最新數(shù)據(jù)
if (mIsNetworkEnabled) {
// 如果網(wǎng)絡(luò)可用右蒲,則加載網(wǎng)絡(luò)數(shù)據(jù)
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(MainActivity.LOADING_DURATION);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
// 加載完畢后在UI線程結(jié)束下拉刷新
mRefreshLayout.endRefreshing();
mDatas.addAll(0, DataEngine.loadNewData());
mAdapter.setDatas(mDatas);
}
}.execute();
} else {
// 網(wǎng)絡(luò)不可用阀湿,結(jié)束下拉刷新
Toast.makeText(this, "網(wǎng)絡(luò)不可用", Toast.LENGTH_SHORT).show();
mRefreshLayout.endRefreshing();
}
}
@Override
public boolean onBGARefreshLayoutBeginLoadingMore(BGARefreshLayout refreshLayout) {
// 在這里加載更多數(shù)據(jù),或者更具產(chǎn)品需求實(shí)現(xiàn)上拉刷新也可以
if (mIsNetworkEnabled) {
// 如果網(wǎng)絡(luò)可用瑰妄,則異步加載網(wǎng)絡(luò)數(shù)據(jù)陷嘴,并返回true,顯示正在加載更多
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(MainActivity.LOADING_DURATION);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
// 加載完畢后在UI線程結(jié)束加載更多
mRefreshLayout.endLoadingMore();
mAdapter.addDatas(DataEngine.loadMoreData());
}
}.execute();
return true;
} else {
// 網(wǎng)絡(luò)不可用间坐,返回false灾挨,不顯示正在加載更多
Toast.makeText(this, "網(wǎng)絡(luò)不可用", Toast.LENGTH_SHORT).show();
return false;
}
}
// 通過代碼方式控制進(jìn)入正在刷新狀態(tài)。應(yīng)用場景:某些應(yīng)用在activity的onStart方法中調(diào)用竹宋,自動(dòng)進(jìn)入正在刷新狀態(tài)獲取最新數(shù)據(jù)
public void beginRefreshing() {
mRefreshLayout.beginRefreshing();
}
// 通過代碼方式控制進(jìn)入加載更多狀態(tài)
public void beginLoadingMore() {
mRefreshLayout.beginLoadingMore();
}
}
但這個(gè)庫有一個(gè)嚴(yán)重的bug
正在刷新或加載更多時(shí)劳澄,用戶上下滑動(dòng)不會(huì)讓下拉刷新視圖和加載更多視圖跟著滑動(dòng)
這一點(diǎn)在網(wǎng)絡(luò)慢的時(shí)候,非常影響用戶體驗(yàn)
四蜈七、CommonPullToRefresh
這個(gè)庫基于android-Ultra-Pull-To-Refresh秒拔,封裝了加載更多
的邏輯,而且還支持Android最新推出的下拉控件** SwipeRefreshLayout**
集成步驟同樣簡單:
- 一行導(dǎo)包
compile 'com.chanven.lib:cptr:1.0.0'
- 界面邏輯
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.chanven.lib.cptr.PtrClassicFrameLayout
android:id="@+id/test_list_view_frame"
xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f0f0f0"
cube_ptr:ptr_resistance="1.7"
cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
cube_ptr:ptr_duration_to_close="200"
cube_ptr:ptr_duration_to_close_header="1000"
cube_ptr:ptr_keep_header_when_refresh="true"
cube_ptr:ptr_pull_to_fresh="false">
<ListView
android:id="@+id/test_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:choiceMode="singleChoice"
android:divider="#b0b0b0"
android:dividerHeight="0.1dp"
android:fadingEdge="none"
android:scrollbarStyle="outsideOverlay"/>
</com.chanven.lib.cptr.PtrClassicFrameLayout>
</LinearLayout>
- 控制邏輯
這一塊可以使用android-Ultra-Pull-To-Refresh的方式飒硅,也可以使用** SwipeRefreshLayout**的方式溯警,看需求了。
我現(xiàn)在選擇的下拉刷新庫就是CommonPullToRefresh狡相,目前使用中還沒有發(fā)現(xiàn)問題。
Panda
2016-06-13