实现 ListView 的上拉刷新和下拉刷新,需要使用 ListView 的 setOnScrollListener() 监听器,具体的内容如代码中的注释。效果如下:
MainActivity.java :
package com.android.pulltorefresh;
import java.util.ArrayList;
import com.android.pulltorefresh.MyListView.OnRefreshListener;
import android.app.Activity;
import android.app.ProgressDialog;
import android.gesture.Gesture;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
private ArrayAdapter adapter;
private ArrayList<String> data;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyListView myListView = (MyListView)findViewById(R.id.myList);
data = new ArrayList<String>();
// 此处只是为了测试刷新,故此给出了19个数,
// 如果给出的数目小于当前屏幕所能容纳的 ListView 列表项,则会出 bug (顶部,底部同时刷新)
// 如果想要解决该 bug 可以使用 Gesture,通过 上下滑动的速度来控制刷新
for (int i = 1; i < 20; i++){
data.add("第i个数据:" + i);
}
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
myListView.setAdapter(adapter);
myListView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onTopRefresh() {
addTopData();
}
@Override
public void onBottomRefresh() {
addBottomData();
}
});
// 此部分应该从 MainActivity 中分离出去(如 MyListView.java),减少代码的耦合度,增加扩展性
/* myListView.setOnScrollListener(new OnScrollListener() {
private int firstVisibleItem, visibleItemCount, totalItemCount;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
if (firstVisibleItem == 0) {
addTopData();
}
// 有 bug
if (firstVisibleItem + visibleItemCount == totalItemCount) {
addBottomData();
}
}
}
@Override
public void onScroll(AbsListView view,
int firstVisibleItem,
int visibleItemCount,
int totalItemCount) {
this.firstVisibleItem = firstVisibleItem;
this.visibleItemCount = visibleItemCount;
this.totalItemCount = totalItemCount;
}
});*/
}
/**
* 在顶部添加数据(刷新)
*/
protected void addTopData() {
/* 此处只是为了测试刷新,让其 3 秒刷新一次 ,
* 可在 AsyncTask 中使用 ProgressDialog 加载下载图片时的进度对话框增加其效果*/
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
data.add(0, "头部新增的数据:" + (data.size() + 1));
adapter.notifyDataSetChanged();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
/**
* 在底部添加数据(刷新)
*/
protected void addBottomData() {
data.add("底部新增的数据:" + (data.size() + 1));
adapter.notifyDataSetChanged();
}
}
MyListView.java :
package com.android.pulltorefresh;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.AbsListView;
import android.widget.ListView;
public class MyListView extends ListView{
/* 接口对象 */
public OnRefreshListener mOnRefreshListener;
/**
* 定义一个回调接口,供使用者调用(与使用者实现交互)
*/
public interface OnRefreshListener{
// 下拉刷新
public void onTopRefresh();
// 上拉刷新
public void onBottomRefresh();
}
/**
* 供使用者调用的方法,该方法中有接口所定义的两个 刷新方法;
*/
public void setOnRefreshListener(OnRefreshListener refresh){
mOnRefreshListener = refresh;
/* MyListView 的刷新监听器 */
setOnScrollListener(new OnScrollListener() {
private int firstVisibleItem,
visibleItemCount,
totalItemCount;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
if (firstVisibleItem == 0) {
// 回调在接口中定义的 下拉刷新
mOnRefreshListener.onTopRefresh();
}
// 有 bug(如在 MainActivity.java 所说)
if (firstVisibleItem + visibleItemCount == totalItemCount) {
// 回调在接口中定义的 上拉刷新
mOnRefreshListener.onBottomRefresh();
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// 初始化,滑动 ListView 时的3种状态
this.firstVisibleItem = firstVisibleItem;
this.visibleItemCount = visibleItemCount;
this.totalItemCount = totalItemCount;
}
});
}
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
activity.java :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.android.pulltorefresh.MainActivity" >
<com.android.pulltorefresh.MyListView
android:id="@+id/myList"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>