![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39zM3ETM0IDN3EjNwATM2EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
1.定義個類繼承ListView
添加頭條目
添加腳條目
設定滾動監聽(處理上啦加載)
重寫觸摸 事件(處理下拉重新整理)
public class PullToReFreshListView extends ListView implements OnScrollListener {
private View headerView;
private int headermeasuredHeight;
private RotateAnimation up;
private RotateAnimation down;
private int downY;
/** 下拉重新整理 **/
public static final int PULL_DOWN = 1;
/** 松開重新整理 **/
public static final int RELEASE_REFRESH = 2;
/** 正在重新整理 **/
public static final int REGFRESHING = 3;
/** 目前的狀态 **/
public static int CURRENTSTATE = PULL_DOWN;
private ImageView mArrow;
private ProgressBar mPb;
private TextView mText;
private int footermeasuredHeight;
private View footerview;
/**是否加載更多,true:加載更多,false:沒有加載更多**/
private boolean isLoadMore;
public PullToReFreshListView(Context context) {
// super(context);
this(context, null);
}
public PullToReFreshListView(Context context, AttributeSet attrs) {
// super(context, attrs);
this(context, attrs, 0);
}
public PullToReFreshListView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
// 添加重新整理頭
addHeader();
// 添加底部條目
addFooter();
// 監聽listview的滾動狀态
setOnScrollListener(this);
}
/**
* 添加listview底部條目 2016-8-14 上午11:34:23
*/
private void addFooter() {
footerview = View.inflate(getContext(), R.layout.footer_item, null);
// 隐藏底部條目
footerview.measure(0, 0);
footermeasuredHeight = footerview.getMeasuredHeight();
footerview.setPadding(0, 0, 0, -footermeasuredHeight);
addFooterView(footerview);// 添加listview的底部條目
}
/**
* 添加listview的重新整理頭 2016-8-14 上午9:53:18
*/
private void addHeader() {
headerView = View.inflate(getContext(), R.layout.header_item, null);
// 初始化控件
mArrow = (ImageView) headerView.findViewById(R.id.arrow);
mPb = (ProgressBar) headerView.findViewById(R.id.pb);
mText = (TextView) headerView.findViewById(R.id.text);
// 隐藏重新整理頭
headerView.measure(0, 0);// 測量控件 測量規格為未指定
headermeasuredHeight = headerView.getMeasuredHeight();
headerView.setPadding(0, -headermeasuredHeight, 0, 0);
addHeaderView(headerView);// 将view對象,添加到listview的頭部
initAnimation();
}
/**
* 初始化動畫 2016-8-14 上午10:19:53
*/
private void initAnimation() {
// 箭頭向上
up = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
up.setDuration(500);
up.setFillAfter(true);// 保持動畫結束的狀态
// 箭頭向下
down = new RotateAnimation(-180, -360, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
down.setDuration(500);
down.setFillAfter(true);// 保持動畫結束的狀态
}
// 下拉顯示重新整理頭操作
// 1.觸摸listview
// 2.下拉操作
// 3.判斷目前界面顯示的第一個條目是否是listview的第一個條目,是下拉顯示重新整理頭,不是,顯示顯示listview的其他條目
// 1.觸摸listview
@Override
public boolean onTouchEvent(MotionEvent ev) {
// 2.下拉操作
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveY = (int) ev.getY();
int distance = moveY - downY;
// 判斷是否是下拉操作
// 3.判斷目前界面顯示的第一個條目是否是listview的第一個條目,是下拉顯示重新整理頭,不是,顯示顯示listview的其他條目
// getFirstVisiblePosition : 擷取目前界面顯示的第一個條目的位置
if (distance > 0 && getFirstVisiblePosition() == 0) {
// 實作下拉顯示重新整理頭
// 計算空白的區域
// 空白的區域 = 下拉的距離 - 重新整理頭的高度
int paddingTop = distance - headermeasuredHeight;
headerView.setPadding(0, paddingTop, 0, 0);
// 下拉重新整理 -> 松開重新整理
if (paddingTop > 0 && CURRENTSTATE == PULL_DOWN) {
CURRENTSTATE = RELEASE_REFRESH;
switchOption();
}
// 松開重新整理 -> 下拉重新整理
if (paddingTop < 0 && CURRENTSTATE == RELEASE_REFRESH) {
CURRENTSTATE = PULL_DOWN;
switchOption();
}
// 因為系統的listview無法顯示空白區域的,是以使用系統的觸摸事件會出問題,解決:不使用
return true;
}
break;
case MotionEvent.ACTION_UP:
// 松開重新整理 -> 正在重新整理,并且顯示重新整理頭
if (CURRENTSTATE == RELEASE_REFRESH) {
CURRENTSTATE = REGFRESHING;
headerView.setPadding(0, 0, 0, 0);
switchOption();
// 重新整理資料
if (onRefreshListener != null) {
onRefreshListener.regresh();
}
}
// 下拉重新整理 -> 隐藏重新整理頭
if (CURRENTSTATE == PULL_DOWN) {
headerView.setPadding(0, -headermeasuredHeight, 0, 0);
}
break;
}
// 因為隻有是下拉顯示空白區域的時候才需要不使用系統的觸摸事件,但是如果下拉不是空白區域,還是要使用系統的觸摸事件,來實作下拉顯示其他條目的操作的
return super.onTouchEvent(ev);
}
/**
* 根據狀态更改控件的顯示内容 2016-8-14 上午10:55:45
*/
private void switchOption() {
switch (CURRENTSTATE) {
case PULL_DOWN:
// 下拉重新整理
mText.setText("下拉重新整理");
mArrow.startAnimation(down);
break;
case RELEASE_REFRESH:
// 松開重新整理
mText.setText("松開重新整理");
mArrow.startAnimation(up);
break;
case REGFRESHING:
// 正在重新整理
mText.setText("正在重新整理");
mArrow.clearAnimation();// 清除動畫
mArrow.setVisibility(View.GONE);
mPb.setVisibility(View.VISIBLE);
break;
}
}
// 取消重新整理
/**
* 取消重新整理 2016-8-14 上午11:25:34
*/
public void finish() {
// 正在重新整理 -> 下拉重新整理,并且隐藏重新整理頭
if (CURRENTSTATE == REGFRESHING) {
CURRENTSTATE = PULL_DOWN;
mText.setText("下拉重新整理");
mPb.setVisibility(View.GONE);
mArrow.setVisibility(View.VISIBLE);
headerView.setPadding(0, -headermeasuredHeight, 0, 0);
}
//取消加載更多
//因為取消下拉重新整理和上拉加載是在一個方法中,為了避免取消下拉重新整理的時候,同時也會取消上拉加載,設定是否加載更多的标示
if (isLoadMore) {
footerview.setPadding(0, 0, 0, -footermeasuredHeight);
isLoadMore = false;
}
}
// 加載更多
// 1.監聽listview的滾動狀态,如果是停止滾動,顯示加載更多條目,
// 2.上拉到listview的最後一個條目
// 當listview滾動狀态改變的時候調用的方法
// scrollState : listview滾動的狀态
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 監聽listview的滾動狀态,如果是停止滾動,顯示加載更多條目,上拉到listview的最後一個條目
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
&& getLastVisiblePosition() == getCount() - 1 && isLoadMore == false) {
isLoadMore = true;
// 顯示加載更多條目
footerview.setPadding(0, 0, 0, 0);
// 重新定位listview顯示的最後一個條目
setSelection(getCount() - 1);// 跳轉到listview的哪個條目,position : 條目的位置
// 加載更多資料
if (onRefreshListener != null) {
onRefreshListener.loadmore();
}
}
}
// 當listview滾動的時候調用的方法
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
// 回調函數實作重新整理資料操作
// 3.建立儲存接口實作對象的變量
public OnRefreshListener onRefreshListener;
// 2.建立擷取接口實作對象的方法
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
this.onRefreshListener = onRefreshListener;
}
// 1.建立接口
public interface OnRefreshListener {
/** 下拉重新整理 **/
public void regresh();
/**加載更多資料**/
public void loadmore();
}
2.activity
public class MainActivity extends Activity {
private PullToReFreshListView mListView;
private int m;
private int n;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
/**
* 初始化控件
* 2016-8-14 上午9:31:39
*/
private void initView() {
mListView = (PullToReFreshListView) findViewById(R.id.listview);
final List<String> list = new ArrayList<String>();
//填充資料
for (int i = 0; i < 10; i++) {
list.add("德瑪西亞"+i+"區");
}
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
mListView.setAdapter(arrayAdapter);
//重新整理資料操作
mListView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void regresh() {
//加載資料
//延遲一段時間,加載資料
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//list.add("艾歐尼亞"+(++m)+"區");
list.add(0, "艾歐尼亞"+(++m)+"區");//将資料添加list集合的哪個位置,location : 位置 object:添加的資料
//重新整理界面
arrayAdapter.notifyDataSetChanged();
//取消重新整理
mListView.finish();
}
}, 3000);//delayMillis : 延遲時間 Runnable : 執行的操作
}
@Override
public void loadmore() {
//延遲一段時間,加載資料
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//list.add("艾歐尼亞"+(++m)+"區");
list.add("黑色玫瑰"+(++n)+"區");//将資料添加list集合的哪個位置,location : 位置 object:添加的資料
//重新整理界面
arrayAdapter.notifyDataSetChanged();
//取消重新整理
mListView.finish();
}
}, 3000);//delayMillis : 延遲時間 Runnable : 執行的操作
}
});
}
3.布局檔案
<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"
>
<com.itheima.pulltorefreshlistview.PullToReFreshListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@android:color/darker_gray"
android:dividerHeight="0.5dp"
></com.itheima.pulltorefreshlistview.PullToReFreshListView>
</RelativeLayout>
4.頭條目布局
<?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="wrap_content"
android:orientation="horizontal"
android:padding="6dp"
>
<RelativeLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
>
<ImageView
android:id="@+id/arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/arrow"
android:layout_centerInParent="true"
/>
<ProgressBar
android:id="@+id/pb"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:indeterminateDrawable="@drawable/progressbarstyle"
android:visibility="gone"
/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:gravity="center_vertical|center_horizontal"
>
<!-- | : 加意思,兩種效果全部生效 -->
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉重新整理"
android:textColor="#FF0000"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="最後刷時間:2016-08-14 09:48:06"
android:textColor="@android:color/darker_gray"
/>
</LinearLayout>
</LinearLayout>
5.腳條目布局檔案
<?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="wrap_content"
android:orientation="horizontal"
android:gravity="center"
>
<ProgressBar
android:id="@+id/pb"
android:layout_width="30dp"
android:layout_height="30dp"
android:indeterminateDrawable="@drawable/progressbarstyle"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
/>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="加載更多..."
android:textColor="#FF0000"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
/>
</LinearLayout>