是现今主流的下拉刷新和上拉加载更多ListView;
有等待动画和箭头指示,还可以显示最后更新时间.
废话不多说,直接上代码.有注释,可以慢慢看
package com.spider.reader.view;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.spider.reader.R;
/***
* 自定义拖拉刷新和加载更多ListView
*
* @author Seal Created on 2013-11-19 下午5:30:15
*/
public class PullToRefreshAndLoadMoreListView extends ListView implements
OnScrollListener, OnClickListener {
// 下拉ListView枚举所有状态
private enum PullDownState {
LV_NORMAL, // 普通状态
LV_PULL_REFRESH, // 下拉状态(为超过mHeadViewHeight)
LV_RELEASE_REFRESH, // 松开可刷新状态(超过mHeadViewHeight)
LV_LOADING;// 加载状态
}
// 点击加载更多枚举所有状态
private enum PullUpState {
LV_NORMAL, // 普通状态
LV_PULL_LOAD, // 上拉状态(为超过mFootViewHeight)
LV_RELEASE_LOAD, // 松开可刷新状态(超过mFootViewHeight)
LV_LOADING;// 加载状态
}
private Context context;
private View mHeadView, mFootView;// 头部headView
private int mHeadViewWidth; // headView的宽(mHeadView)
private int mHeadViewHeight;// headView的高(mHeadView)
private int mFootViewWidth; // headView的宽(mFootView)
private int mFootViewHeight;// headView的高(mFootView)
private int mFirstItemIndex = -1;// 当前视图能看到的第一个项的索引
private int mLastItemIndex = -1;// 当前视图中是否是最后一项.
// 用于保证startY的值在一个完整的touch事件中只被记录一次
private boolean mIsRecord = false;// 针对下拉
private boolean mIsRecord_B = false;// 针对上拉
private boolean mBack = false;// headView是否返回.
private int mStartY, mMoveY;// 按下是的y坐标,move时的y坐标
private PullDownState mPullDownState = PullDownState.LV_NORMAL;// 拖拉状态.(自定义枚举)
private PullUpState mPullUpState = PullUpState.LV_NORMAL;// 加载更多默认状态.
private final static int RATIO = 2;// 手势下拉距离比.
private boolean isScroller = true;// 是否屏蔽ListView滑动。
private TextView mRefreshTextview; // 刷新msg(mHeadView)
private TextView mLastUpdateTextView;// 更新事件(mHeadView)
private ImageView mArrowImageView;// 下拉图标(mHeadView)
private ImageView mHeadProgressImage;// 刷新进度体(mHeadView)
private TextView mFootRefreshTextview; // 刷新msg(mFootView)
private TextView mFootLastUpdateTextView;// 更新事件(mFootView)
private ImageView mFootArrowImageView;// 下拉图标(mFootView)
private ImageView mFootProgressImage;// 刷新进度体(mFootView)
private Animation animation, reverseAnimation, footAnimation,
footReverseAnimation;// 旋转动画,旋转动画之后旋转动画.
private MyAsynTask myAsynTask;// 任务
private OnRefreshAndLoadingMoreListener onRefreshAndLoadingMoreListener;// 下拉刷新接口(自定义)
private Animation loadingAnimation;
private SimpleDateFormat sdf;
public final static int LIST_PULL_DOWN = 1, LIST_PULL_UP = 2,
HEAD_DOWN = 3, FOOT_UP = 4;
public PullToRefreshAndLoadMoreListView(Context context) {
super(context, null);
this.context = context;
initDragListView(context);
}
public PullToRefreshAndLoadMoreListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initDragListView(context);
}
// 注入下拉刷新接口
public void setOnRefreshListener(
OnRefreshAndLoadingMoreListener onRefreshLoadingMoreListener) {
this.onRefreshAndLoadingMoreListener = onRefreshLoadingMoreListener;
}
/***
* 初始化ListView
*/
public void initDragListView(Context context) {
initHeadView(context);// 初始化该head.
initFooterView(context);// 初始化footer
setOnScrollListener(this);// ListView滚动监听
}
/***
* 初始话头部HeadView
*
* @param context
* 上下文
* @param time
* 上次更新时间
*/
public void initHeadView(Context context) {
mHeadView = LayoutInflater.from(context).inflate(
R.layout.pull_to_refresh_head_layout, null);
mArrowImageView = (ImageView) mHeadView
.findViewById(R.id.head_arrowImageView);
mArrowImageView.setMinimumWidth(60);
mHeadProgressImage = (ImageView) mHeadView
.findViewById(R.id.head_load_progressBar);
mRefreshTextview = (TextView) mHeadView
.findViewById(R.id.head_tipsTextView);
mLastUpdateTextView = (TextView) mHeadView
.findViewById(R.id.head_lastUpdatedTextView);
// 显示更新事件
sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
measureView(mHeadView);
// 获取宽和高
mHeadViewWidth = mHeadView.getMeasuredWidth();
mHeadViewHeight = mHeadView.getMeasuredHeight();
addHeaderView(mHeadView, null, false);// 将初始好的ListView add进拖拽ListView
// 在这里我们要将此headView设置到顶部不显示位置.
mHeadView.setPadding(0, -1 * mHeadViewHeight, 0, 0);
initAnimation();
}
/***
* 初始化底部加载更多控件
*/
private void initFooterView(Context context) {
mFootView = LayoutInflater.from(context).inflate(
R.layout.pull_to_refresh_head_layout, null);
mFootArrowImageView = (ImageView) mFootView
.findViewById(R.id.head_arrowImageView);
mFootArrowImageView.setImageDrawable(context.getResources()
.getDrawable(R.drawable.pulltorefresh_up_arrow));
mFootArrowImageView.setMinimumWidth(60);
mFootProgressImage = (ImageView) mFootView
.findViewById(R.id.head_load_progressBar);
mFootRefreshTextview = (TextView) mFootView
.findViewById(R.id.head_tipsTextView);
mFootRefreshTextview.setText("上拉可以加载更多");
mFootLastUpdateTextView = (TextView) mFootView
.findViewById(R.id.head_lastUpdatedTextView);
measureView(mFootView);
// 获取宽和高
mFootViewWidth = mFootView.getMeasuredWidth();
mFootViewHeight = mFootView.getMeasuredHeight();
addFooterView(mFootView, null, false);// 将初始好的ListView add进拖拽ListView
// 在这里我们要将此FooterView设置到底部不显示位置.
mFootView.setPadding(0, 0, 0, -1 * mFootViewHeight);
}
/***
* 初始化动画
*/
private void initAnimation() {
// 旋转动画
animation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
animation.setInterpolator(new LinearInterpolator());// 匀速
animation.setDuration(200);
animation.setFillAfter(true);// 停留在最后状态.
// 反向旋转动画
reverseAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
reverseAnimation.setInterpolator(new LinearInterpolator());
reverseAnimation.setDuration(200);
reverseAnimation.setFillAfter(true);
// 旋转动画
footAnimation = new RotateAnimation(0, 180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
footAnimation.setInterpolator(new LinearInterpolator());// 匀速
footAnimation.setDuration(200);
footAnimation.setFillAfter(true);// 停留在最后状态.
// 反向旋转动画
footReverseAnimation = new RotateAnimation(180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
footReverseAnimation.setInterpolator(new LinearInterpolator());
footReverseAnimation.setDuration(200);
footReverseAnimation.setFillAfter(true);
loadingAnimation = AnimationUtils.loadAnimation(context,
R.anim.loading_progress);
}
/***
* 作用:测量 headView的宽和高.
*
* @param child
*/
private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
int lpHeight = p.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
/***
* touch 事件监听
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
// 按下
case MotionEvent.ACTION_DOWN:
doActionDown_B(ev);
doActionDown(ev);
break;
// 移动
case MotionEvent.ACTION_MOVE:
doActionMove_B(ev);
doActionMove(ev);
break;
// 抬起
case MotionEvent.ACTION_UP:
doActionUp_B(ev);
doActionUp(ev);
break;
default:
break;
}
//
// /***
// * 如果是ListView本身的拉动,那么返回true,这样ListView不可以拖动.
// * 如果不是ListView的拉动,那么调用父类方法,这样就可以上拉执行.
// */
/**
* isScroller==true:可以滑动ListView
* isScroller==false:不可以滑动ListView,因为不调用父类的事件处理方法,所以没用对应的滑动事件处理.
*/
if (isScroller) {
return super.onTouchEvent(ev);
} else {
return true;
}
}
/***
* 摁下操作
*
* 作用:获取摁下是的y坐标
*
* @param event
*/
void doActionDown(MotionEvent event) {
// 如果是第一项且是一次touch
if (mIsRecord == false && mFirstItemIndex == 0) {
mStartY = (int) event.getY();
mIsRecord = true;
}
}
/***
* 摁下操作 底部
*
* 作用:获取摁下是的y坐标
*/
void doActionDown_B(MotionEvent event) {
// 如果是第一项且是一次touch
if (mIsRecord_B == false && mLastItemIndex == getCount()) {
mStartY = (int) event.getY();
mIsRecord_B = true;
}
}
/***
* 拖拽移动操作
*
* @param event
*/
void doActionMove(MotionEvent event) {
// 判断是否是第一项,若不是直接返回
mMoveY = (int) event.getY();// 获取实时滑动y坐标
// 检测是否是一次touch事件.
if (mIsRecord == false && mFirstItemIndex == 0) {
mStartY = (int) event.getY();
mIsRecord = true;
}
/***
* 如果touch关闭或者正处于Loading状态的话 return.
*/
if (mIsRecord == false || mPullDownState == PullDownState.LV_LOADING) {
return;
}
// 向下啦headview移动距离为y移动的一半.(比较友好)
int offset = (mMoveY - mStartY) / RATIO;
switch (mPullDownState) {
// 普通状态
case LV_NORMAL: {
// 说明下拉
if (offset > 0) {
// 设置headView的padding属性.
mHeadView.setPadding(0, offset - mHeadViewHeight, 0, 0);
switchViewState(PullDownState.LV_PULL_REFRESH);// 下拉状态
}
}
break;
// 下拉状态
case LV_PULL_REFRESH: {
setSelection(0);// 时时保持在顶部.
// 设置headView的padding属性.
mHeadView.setPadding(0, offset - mHeadViewHeight, 0, 0);
if (offset < 0) {
// /***
// * 要明白为什么isScroller = false;
// */
// isScroller = false;
switchViewState(PullDownState.LV_NORMAL);// 普通状态
} else if (offset > mHeadViewHeight) {// 如果下拉的offset超过headView的高度则要执行刷新.
switchViewState(PullDownState.LV_RELEASE_REFRESH);// 更新为可刷新的下拉状态.
}
}
break;
// 可刷新状态
case LV_RELEASE_REFRESH: {
setSelection(0);
// 设置headView的padding属性.
mHeadView.setPadding(0, offset - mHeadViewHeight, 0, 0);
// 下拉offset>0,但是没有超过headView的高度.那么要goback 原装.
if (offset >= 0 && offset <= mHeadViewHeight) {
mBack = true;
switchViewState(PullDownState.LV_PULL_REFRESH);
} else if (offset < 0) {
switchViewState(PullDownState.LV_NORMAL);
} else {
}
}
break;
default:
return;
}
}
void doActionMove_B(MotionEvent event) {
mMoveY = (int) event.getY();// 获取实时滑动y坐标
// 检测是否是一次touch事件.(若mFirstItemIndex为0则要初始化mStartY)
if (mIsRecord_B == false && mLastItemIndex == getCount()) {
mStartY = (int) event.getY();
mIsRecord_B = true;
}
/***
* 如果touch关闭或者正处于Loading状态的话 return.
*/
if (mIsRecord_B == false || mPullUpState == PullUpState.LV_LOADING) {
return;
}
// 向下啦headview移动距离为y移动的一半.(比较友好)
int offset = (mMoveY - mStartY) / RATIO;
switch (mPullUpState) {
// 普通状态
case LV_NORMAL: {
// 说明上拉
if (offset < 0) {
int distance = Math.abs(offset);
// 设置headView的padding属性.
mFootView.setPadding(0, 0, 0, distance - mFootViewHeight);
switchViewState(PullUpState.LV_PULL_LOAD);// 上拉状态
}
}
break;
// 上拉状态
case LV_PULL_LOAD: {
setSelection(getCount() - 1);// 时时保持最底部
// 设置headView的padding属性.
int distance = Math.abs(offset);
mFootView.setPadding(0, 0, 0, distance - mFootViewHeight);
// 说明下滑
if (offset > 0) {
// /***
// * 要明白为什么isScroller = false;
// */
// isScroller = false;
switchViewState(PullUpState.LV_NORMAL);// 普通状态
} else if (offset < -mFootViewHeight) {// 如果上拉的offset超过headView的高度则要变为松开后执行刷新状态.
switchViewState(PullUpState.LV_RELEASE_LOAD);// 更新为可刷新的下拉状态.
}
}
break;
// 可加载状态
case LV_RELEASE_LOAD: {
setSelection(getCount() - 1);// 时时保持最底部
// 设置headView的padding属性.
int distance = Math.abs(offset);
mFootView.setPadding(0, 0, 0, distance - mFootViewHeight);
// 下拉offset>0,但是没有超过headView的高度.那么要goback 原装.
if (offset <= 0 && offset >= -mFootViewHeight) {
mBack = true;
switchViewState(PullUpState.LV_PULL_LOAD);
} else if (offset > 0) {
switchViewState(PullUpState.LV_NORMAL);
}
}
break;
default:
return;
}
}
/***
* 手势抬起操作
*
* @param event
*/
public void doActionUp(MotionEvent event) {
mIsRecord = false;// 此时的touch事件完毕,要关闭。
mIsRecord_B = false; // 此时的touch事件完毕,要关闭。
mBack = false;
if (mPullDownState == PullDownState.LV_LOADING) {
return;
}
// 处理相应状态.
switch (mPullDownState) {
// 普通状态
case LV_NORMAL:
break;
// 下拉状态
case LV_PULL_REFRESH:
// 执行相应动画.
switchViewState(PullDownState.LV_NORMAL);
break;
// 刷新状态
case LV_RELEASE_REFRESH:
/***
* 要明白为什么isScroller = false;
*/
isScroller = false;
// 执行相应动画.
switchViewState(PullDownState.LV_LOADING);
onRefresh();// 下拉刷新
break;
default:
break;
}
myAsynTask = new MyAsynTask();
myAsynTask.execute(LIST_PULL_DOWN);
}
private void doActionUp_B(MotionEvent event) {
mIsRecord = false;// 此时的touch事件完毕,要关闭。
mIsRecord_B = false; // 此时的touch事件完毕,要关闭。
mBack = false;
if (mPullUpState == PullUpState.LV_LOADING) {
return;
}// 处理相应状态.
switch (mPullUpState) {
// 普通状态
case LV_NORMAL:
break;
// 下拉状态
case LV_PULL_LOAD:
// 执行相应动画.
switchViewState(PullUpState.LV_NORMAL);
break;
// 刷新状态
case LV_RELEASE_LOAD:
/***
* 要明白为什么isScroller = false;
*/
isScroller = false;
// 执行相应动画.
switchViewState(PullUpState.LV_LOADING);
onLoadMore();// 上拉刷新
break;
default:
break;
}
// 执行相应动画.
myAsynTask = new MyAsynTask();
myAsynTask.execute(LIST_PULL_UP);
}
// 切换headview视图
private void switchViewState(PullDownState state) {
switch (state) {
// 普通状态
case LV_NORMAL: {
mArrowImageView.clearAnimation();// 清除动画
mHeadProgressImage.clearAnimation();
mArrowImageView
.setImageResource(R.drawable.pulltorefresh_down_arrow);
}
break;
// 下拉状态
case LV_PULL_REFRESH: {
mHeadProgressImage.setVisibility(View.GONE);// 隐藏进度条
mArrowImageView.setVisibility(View.VISIBLE);// 下拉图标
mRefreshTextview.setText("下拉可以刷新");
mArrowImageView.clearAnimation();// 清除动画
// 是有可刷新状态(LV_RELEASE_REFRESH)转为这个状态才执行,其实就是你下拉后在上拉会执行.
if (mBack) {
mBack = false;
mArrowImageView.clearAnimation();// 清除动画
mArrowImageView.startAnimation(reverseAnimation);// 启动反转动画
}
}
break;
// 松开刷新状态
case LV_RELEASE_REFRESH: {
mHeadProgressImage.setVisibility(View.GONE);// 隐藏进度条
mArrowImageView.setVisibility(View.VISIBLE);// 显示下拉图标
mRefreshTextview.setText("松开即可刷新");
mArrowImageView.clearAnimation();// 清除动画
mArrowImageView.startAnimation(animation);// 启动动画
}
break;
// 加载状态
case LV_LOADING: {
Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_LOADING");
mHeadProgressImage.setVisibility(View.VISIBLE);
mHeadProgressImage.startAnimation(loadingAnimation);
mArrowImageView.clearAnimation();
mArrowImageView.setVisibility(View.GONE);
mRefreshTextview.setText("载入中...");
}
break;
default:
return;
}
// 切记不要忘记时时更新状态。
mPullDownState = state;
}
// 切换footView视图
private void switchViewState(PullUpState state) {
switch (state) {
// 普通状态
case LV_NORMAL: {
mFootArrowImageView.clearAnimation();// 清除动画
mFootProgressImage.clearAnimation();
mFootArrowImageView
.setImageResource(R.drawable.pulltorefresh_up_arrow);
}
break;
// 下拉状态
case LV_PULL_LOAD: {
mFootProgressImage.setVisibility(View.GONE);// 隐藏进度条
mFootArrowImageView.setVisibility(View.VISIBLE);// 下拉图标
mFootRefreshTextview.setText("上拉可以加载更多");
mFootArrowImageView.clearAnimation();// 清除动画
// 是有可加载状态(LV_RELEASE_LOAD)转为这个状态才执行,其实就是你上拉后在下拉会执行.
if (mBack) {
mBack = false;
mFootArrowImageView.clearAnimation();// 清除动画
mFootArrowImageView.startAnimation(footReverseAnimation);// 启动反转动画
}
}
break;
// 松开加载更多状态
case LV_RELEASE_LOAD: {
mFootProgressImage.setVisibility(View.GONE);// 隐藏进度条
mFootArrowImageView.setVisibility(View.VISIBLE);// 显示下拉图标
mFootRefreshTextview.setText("松开即可加载更多");
mFootArrowImageView.clearAnimation();// 清除动画
mFootArrowImageView.startAnimation(footAnimation);// 启动动画
}
break;
// 加载状态
case LV_LOADING: {
Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_LOADING");
mFootProgressImage.setVisibility(View.VISIBLE);
mFootProgressImage.startAnimation(loadingAnimation);
mFootArrowImageView.clearAnimation();
mFootArrowImageView.setVisibility(View.GONE);
mFootRefreshTextview.setText("载入中...");
}
break;
default:
return;
}
// 切记不要忘记时时更新状态。
mPullUpState = state;
}
/***
* ListView 滑动监听
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
mFirstItemIndex = firstVisibleItem;
mLastItemIndex = firstVisibleItem + visibleItemCount;
}
@Override
public void onClick(View v) {
}
/***
* 下拉刷新
*/
private void onRefresh() {
if (onRefreshAndLoadingMoreListener != null) {
onRefreshAndLoadingMoreListener.onRefresh();
}
}
/***
* 下拉刷新完毕
*/
public void onRefreshComplete() {
mHeadProgressImage.clearAnimation();
mRefreshTextview.setText("刷新完成");
mLastUpdateTextView.setText("最后更新:" + sdf.format(new Date()));// 修改更新后的界面时间
// 执行相应动画.
myAsynTask = new MyAsynTask();
myAsynTask.execute(HEAD_DOWN);
}
private void onLoadMore() {
if (onRefreshAndLoadingMoreListener != null) {
onRefreshAndLoadingMoreListener.onLoadMore();
}
}
/***
* 下拉刷新完毕
*/
public void onLoadMoreComplete() {
mFootProgressImage.clearAnimation();
mFootRefreshTextview.setText("加载完成");
mFootLastUpdateTextView.setText("最后加载:" + sdf.format(new Date()));// 修改更新后的界面时间
// 执行相应动画.
myAsynTask = new MyAsynTask();
myAsynTask.execute(FOOT_UP);
}
/**
* 载入失败时调用恢复正常ListView 进行上拉或下拉后必须调用此方法
*
* @param flag
* flag==HEAD_DOWN:表示刷新失败 flag==FOOT_UP:表示加载更多失败
*/
public void loadOrRefreshFailed(int flag) {
if (flag == HEAD_DOWN) {
mHeadProgressImage.clearAnimation();
mRefreshTextview.setText("载入失败");
} else {
mFootProgressImage.clearAnimation();
mFootRefreshTextview.setText("载入失败");
}
// 执行相应动画.
myAsynTask = new MyAsynTask();
myAsynTask.execute(flag);
}
/***
* 用于产生动画
*
* @author Seal Created on 2013-11-20 下午3:58:56
*/
private class MyAsynTask extends AsyncTask<Integer, Integer, Void> {
private final static int STEP = 15;// 步伐
private final static int TIME = 8;// 休眠时间
private int distance;// 距离(该距离指的是:mHeadView的PaddingTop+mHeadView的高度,及默认位置状态.)
private int number;// 循环执行次数.
private int disPadding;// 时时padding距离.
private int upOrDown;// 标志上拉刷新还是下拉加载更多还是头和脚的上拉和下拉的恢复
@Override
protected Void doInBackground(Integer... params) {
try {
this.upOrDown = params[0];
switch (upOrDown) {
case LIST_PULL_DOWN:
if (mPullDownState == PullDownState.LV_LOADING) {
distance = mHeadView.getPaddingTop();
} else {
distance = mHeadView.getPaddingTop()
+ Math.abs(mHeadViewHeight);
}
break;
case LIST_PULL_UP:
// 获取距离.
if (mPullUpState == PullUpState.LV_LOADING) {
distance = mFootView.getPaddingBottom();
} else {
distance = mFootView.getPaddingBottom()
+ Math.abs(mFootViewHeight);
}
break;
case HEAD_DOWN:
Thread.sleep(500);// 延迟0.5S用于看到更新完的显示头和脚
distance = Math.abs(mHeadViewHeight);
break;
case FOOT_UP:
Thread.sleep(500);
distance = Math.abs(mFootViewHeight);
break;
default:
break;
}
// 获取循环次数.
if (distance % STEP == 0) {
number = distance / STEP;
} else {
number = distance / STEP + 1;
}
// 进行循环.
for (int i = 0; i < number; i++) {
if (upOrDown == HEAD_DOWN || upOrDown == FOOT_UP) {
Thread.sleep(6 * TIME);// 如果是头和脚则延长动画时间
} else {
Thread.sleep(TIME);
}
publishProgress(STEP);
}
if (upOrDown == HEAD_DOWN) {
publishProgress(HEAD_DOWN);
} else if (upOrDown == FOOT_UP) {
publishProgress(FOOT_UP);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
/**
* 处理动画
*/
switch (upOrDown) {
case LIST_PULL_DOWN:
disPadding = Math.max(mHeadView.getPaddingTop() - STEP, -1
* mHeadViewHeight);
mHeadView.setPadding(0, disPadding, 0, 0);// 回归.
break;
case HEAD_DOWN:
disPadding = Math.max(mHeadView.getPaddingTop() - STEP, -1
* mHeadViewHeight);
mHeadView.setPadding(0, disPadding, 0, 0);// 回归.
break;
case LIST_PULL_UP:
disPadding = Math.max(mFootView.getPaddingBottom() - STEP, -1
* mHeadViewHeight);
mFootView.setPadding(0, 0, 0, disPadding);// 回归.
break;
case FOOT_UP:
disPadding = Math.max(mFootView.getPaddingBottom() - STEP, -1
* mHeadViewHeight);
mFootView.setPadding(0, 0, 0, disPadding);// 回归.
break;
default:
break;
}
/**
* 恢复header和footer回退后的状态设置
*/
switch (values[0]) {
case HEAD_DOWN:
isScroller = true;// 当加载动画回退后ListView恢复可以Scrooler滑动.
switchViewState(PullDownState.LV_NORMAL);
break;
case FOOT_UP:
isScroller = true;// 当加载动画回退后ListView恢复可以Scrooler滑动.
switchViewState(PullUpState.LV_NORMAL);
break;
default:
break;
}
}
}
/**
* 启动刷新
*/
public void startRefresh() {
setSelection(0);
// 设置headView的padding属性.
mHeadView.setPadding(0, 0, 0, 0);
/***
* 要明白为什么isScroller = false;
*/
isScroller = false;
// 执行相应动画.
switchViewState(PullDownState.LV_LOADING);
onRefresh();// 下拉刷新
}
/***
* 自定义接口
*/
public interface OnRefreshAndLoadingMoreListener {
/***
* // 下拉刷新执行
*/
void onRefresh();
/***
* 上拉加载更多
*/
void onLoadMore();
}
}
pull_to_refeshhead_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- ListView的头部 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<!-- 内容 -->
<RelativeLayout
android:id="@+id/head_contentLayout"
android:layout_width="fill_parent"
android:layout_height="70dp" >
<!-- 箭头图像、进度条 -->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="6dp"
android:layout_toLeftOf="@+id/text_layout" >
<!-- 箭头 -->
<ImageView
android:id="@+id/head_arrowImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/pulltorefresh_down_arrow" />
<!-- 进度条 -->
<ImageView
android:id="@+id/head_load_progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/loading"
android:visibility="gone" />
</FrameLayout>
<!-- 提示、最近更新 -->
<LinearLayout
android:id="@+id/text_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical" >
<!-- 提示 -->
<TextView
android:id="@+id/head_tipsTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉可以刷新"
android:textColor="#999999"
android:textSize="14sp" />
<!-- 最近更新 -->
<TextView
android:id="@+id/head_lastUpdatedTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上次更新"
android:textColor="@color/dark_gray"
android:textSize="10sp"
android:visibility="gone"/>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1px"
android:layout_alignParentBottom="true"
android:background="@color/gray"
android:visibility="gone">
</View>
</RelativeLayout>
</LinearLayout>