下拉刷新、上拉获取更多、左右滑动的ListView

这是根据网上的一篇文章整理的,不记得网址 了


import java.text.SimpleDateFormat;
import java.util.Date;

import com.vsstoo.vbox.R;
import com.vsstoo.vbox.util.AppUtils;


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;


public class CustomListView extends ListView implements OnScrollListener,
OnClickListener {
// status of head
private enum PullDownState {
LV_NORMAL, // normal
LV_PULL_REFRESH, // pull down can refresh
LV_RELEASE_REFRESH, // release can refresh
LV_LOADING;// refreshing


}


// status of foot
private enum PullUpState {
LV_NORMAL, // normal
LV_PULL_LOAD, // pull up can load more
LV_RELEASE_LOAD, // release can load more
LV_LOADING;// loading
}


private Context context;
private View mHeadView, mFootView;// headView


private int mHeadViewHeight;// headView height
private int mFootViewHeight;// footView height


private int mFirstItemIndex = -1;//


private int mLastItemIndex = -1;//


// to promise startY is used once in a touch listener
private boolean mIsRecord = false;// for head


private boolean mIsRecord_B = false;// for foot
private boolean mBack = false;// headView is back or not


private int mStartY, mMoveY;


private int startPos, endPos;
private float startX, startY, endX, endY;


private PullDownState mPullDownState = PullDownState.LV_NORMAL;// down state


private PullUpState mPullUpState = PullUpState.LV_NORMAL;// up state


private final static int RATIO = 2;


private boolean isScroller = true;


private TextView mRefreshTv;
private TextView mLastUpdateTv;
private ImageView mArrowIv;
private ImageView mHeadProgressIv;
private TextView mFootRefreshTv;
private TextView mFootLastUpdateTv;
private ImageView mFootArrowIv;
private ImageView mFootProgressIv;
private Animation animation, reverseAnimation, footAnimation,
footReverseAnimation;


private MyAsynTask myAsynTask;
private OnRefreshListener refreshListener;
private OnLoadMoreListener loadMoreListener;
private OnItemClickListener itemClickListener;
private onSlidListener slidListener;


private Animation loadingAnimation;
private SimpleDateFormat sdf;
public final static int LIST_PULL_DOWN = 1, LIST_PULL_UP = 2,
HEAD_DOWN = 3, FOOT_UP = 4;


private boolean refresh, loadMore, itemClick, slid;
private String refreshLastUpdate;
private String loadMoreLastUpdate;


public CustomListView(Context context) {
super(context, null);
this.context = context;
initDragListView(context);
}


public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initDragListView(context);
}


// set refresh listener
public void setOnRefreshListener(OnRefreshListener refreshListener) {
this.refreshListener = refreshListener;
refresh = true;
}


// set load more listener
public void setOnLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
loadMore = true;
}


// set refresh listener
public void setOnItemClickListener(OnItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
itemClick = true;
}


// set load more listener
public void setOnSlidListener(onSlidListener slidListener) {
this.slidListener = slidListener;
slid = true;
}


/***
* init ListView
*/
public void initDragListView(Context context) {


initHeadView(context);// init head.


initFooterView(context);// init footer


setOnScrollListener(this);// ListView scroll listener
}


// init HeadView
public void initHeadView(Context context) {
mHeadView = LayoutInflater.from(context).inflate(
R.layout.listview_head_foot, null);
mArrowIv = (ImageView) mHeadView.findViewById(R.id.arrowIv);
mArrowIv.setMinimumWidth(60);


mHeadProgressIv = (ImageView) mHeadView.findViewById(R.id.progressIv);


mRefreshTv = (TextView) mHeadView.findViewById(R.id.tipsTv);
mLastUpdateTv = (TextView) mHeadView.findViewById(R.id.lastUpdateTv);
// update time format
sdf = new SimpleDateFormat("yyyy-MM-dd   hh:mm:ss");
measureView(mHeadView);
// get head width and height
// mHeadViewWidth = mHeadView.getMeasuredWidth();
mHeadViewHeight = mHeadView.getMeasuredHeight();


addHeaderView(mHeadView, null, false);// ����ʼ�õ�ListView
// add����קListView
// set head invisible
mHeadView.setPadding(0, -1 * mHeadViewHeight, 0, 0);
initAnimation();


}


// init footer
private void initFooterView(Context context) {
mFootView = LayoutInflater.from(context).inflate(
R.layout.listview_head_foot, null);
mFootArrowIv = (ImageView) mFootView.findViewById(R.id.arrowIv);
mFootArrowIv.setImageDrawable(context.getResources().getDrawable(
R.drawable.refresh));
mFootArrowIv.setRotation(180);
mFootArrowIv.setMinimumWidth(60);


mFootProgressIv = (ImageView) mFootView.findViewById(R.id.progressIv);


mFootRefreshTv = (TextView) mFootView.findViewById(R.id.tipsTv);
mFootRefreshTv.setText(R.string.upCanLoadMore);
mFootLastUpdateTv = (TextView) mFootView
.findViewById(R.id.lastUpdateTv);
measureView(mFootView);
// get footrt width and heught
// mFootViewWidth = mFootView.getMeasuredWidth();
mFootViewHeight = mFootView.getMeasuredHeight();
addFooterView(mFootView, null, false);
// set footer invisible
mFootView.setPadding(0, 0, 0, -1 * mFootViewHeight);
}


// init animation
private void initAnimation() {
// verse animation
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);// stay at the last state
// reverse animation
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);// stay at the last state


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);
}


/***
* get view's width and height

* @param child
*/
private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_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 listener
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {


switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = ev.getX();
startY = ev.getY();
startPos = pointToPosition((int) startX, (int) startY);
doActionDown_B(ev);
doActionDown(ev);
break;
case MotionEvent.ACTION_MOVE:
doActionMove_B(ev);
doActionMove(ev);
break;
case MotionEvent.ACTION_UP:
endX = ev.getX();
endY = ev.getY();
endPos = pointToPosition((int) endX, (int) endY);
AppUtils.write("startX=" + startX + "startY=" + startY + "endX="
+ endX + "endY=" + endY + "startPos=" + startPos
+ "endPos=" + endPos);
AppUtils.write(String.valueOf(slid && startPos != -1
&& startPos == endPos && startX - endX > 30));
AppUtils.write(String.valueOf(itemClick && startPos != -1
&& startX == endX && startY == endY));
if (itemClick && startPos != -1 && startX == endX && startY == endY) {
itemClickListener.onItemClick(startPos-1,
getAdapter().getView(startPos , null, null));
} else if (slid && startPos != -1 && startPos == endPos
&& startX - endX > 30) {
slidListener.onSlid(startPos - 1,
getAdapter().getView(startPos, null, null));
} else {
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();


// 检测是否是一次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 && refresh) {
// 设置headView的padding属性.
mHeadView.setPadding(0, offset - mHeadViewHeight, 0, 0);
switchViewState(PullDownState.LV_PULL_REFRESH);// ����״̬
}
}
break;
// 下拉状态
case LV_PULL_REFRESH: {
setSelection(0);// 时时保持在顶部.
// 设置headView的padding属性.
if (refresh) {


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属性.
if (refresh) {


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 && loadMore && getAdapter().getCount() > 2) {
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);// // 时时保持最底部
// 设置mFootView的padding属性.
if (loadMore && getAdapter().getCount() > 2) {


int distance = Math.abs(offset);
mFootView.setPadding(0, 0, 0, distance - mFootViewHeight);
if (offset > 0) {
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属性.
if (loadMore && getAdapter().getCount() > 2) {


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:
// 执行相应动画.
if (refresh) {


switchViewState(PullDownState.LV_NORMAL);
}
break;
// 刷新状态״̬
case LV_RELEASE_REFRESH:
/***
* Ҫ����ΪʲôisScroller = false;
*/
isScroller = false;
if (refresh) {
// 执行相应动画.
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:
// 执行相应动画.
if (loadMore && getAdapter().getCount() > 2) {


switchViewState(PullUpState.LV_NORMAL);
}
break;
// 刷新状态״̬
case LV_RELEASE_LOAD:
isScroller = false;
// 执行相应动画.
if (loadMore && getAdapter().getCount() > 2) {
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: {
mArrowIv.clearAnimation();// 清除动画
mHeadProgressIv.clearAnimation();
mArrowIv.setImageResource(R.drawable.refresh);
}
break;
// 下拉状态״̬
case LV_PULL_REFRESH: {
mHeadProgressIv.setVisibility(View.GONE);// // 隐藏进度条
mArrowIv.setVisibility(View.VISIBLE);// 下拉图标
mRefreshTv.setText(R.string.downCanRefresh);
mArrowIv.clearAnimation();// 清除动画
if (isEmpty(refreshLastUpdate)) {
mLastUpdateTv.setVisibility(View.GONE);
} else {
mLastUpdateTv.setVisibility(View.VISIBLE);
}
// 是有可刷新状态(LV_RELEASE_REFRESH)转为这个状态才执行,其实就是你下拉后在上拉会执行.
if (mBack) {
mBack = false;
mArrowIv.clearAnimation();// 清除动画
mArrowIv.startAnimation(reverseAnimation);// 启动反转动画
}
}
break;
// 松开刷新状态
case LV_RELEASE_REFRESH: {
mHeadProgressIv.setVisibility(View.GONE);// 隐藏进度条
mArrowIv.setVisibility(View.VISIBLE);// 显示下拉图标
mRefreshTv.setText(R.string.releaseToRefresh);
mArrowIv.clearAnimation();// 清除动画
mArrowIv.startAnimation(animation);// 启动动画
if (isEmpty(refreshLastUpdate)) {
mLastUpdateTv.setVisibility(View.GONE);
} else {
mLastUpdateTv.setVisibility(View.VISIBLE);
}
}
break;
// 加载状态
case LV_LOADING: {
Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_LOADING");
mHeadProgressIv.setVisibility(View.VISIBLE);
mHeadProgressIv.startAnimation(loadingAnimation);
mArrowIv.clearAnimation();
mArrowIv.setVisibility(View.GONE);
mRefreshTv.setText(R.string.loading);
if (isEmpty(refreshLastUpdate)) {
mLastUpdateTv.setVisibility(View.GONE);
} else {
mLastUpdateTv.setVisibility(View.VISIBLE);
}
}
break;
default:
return;
}
// 切记不要忘记时时更新状态。
mPullDownState = state;
}


// 切换footView视图
private void switchViewState(PullUpState state) {


switch (state) {
// 普通状态
case LV_NORMAL: {
mFootArrowIv.clearAnimation();// 清除动画
mFootProgressIv.clearAnimation();
mFootArrowIv.setImageResource(R.drawable.refresh);
}
break;
// 下拉状态
case LV_PULL_LOAD: {
mFootProgressIv.setVisibility(View.GONE);// 隐藏进度条
mFootArrowIv.setVisibility(View.VISIBLE);// 下拉图标
mFootRefreshTv.setText(R.string.upCanLoadMore);
mFootArrowIv.clearAnimation();// 清除动画


if (isEmpty(loadMoreLastUpdate)) {
mFootLastUpdateTv.setVisibility(View.GONE);
} else {
mFootLastUpdateTv.setVisibility(View.VISIBLE);
}
// 是有可加载状态(LV_RELEASE_LOAD)转为这个状态才执行,其实就是你上拉后在下拉会执行.
if (mBack) {
mBack = false;
mFootArrowIv.clearAnimation();// 清除动画
mFootArrowIv.startAnimation(footReverseAnimation);// 启动反转动画
}
}
break;
// 松开加载更多状态
case LV_RELEASE_LOAD: {
mFootProgressIv.setVisibility(View.GONE);// 隐藏进度条
mFootArrowIv.setVisibility(View.VISIBLE);// 显示下拉图标
mFootRefreshTv.setText(R.string.releaseToLoadMore);
mFootArrowIv.clearAnimation();// 清除动画
mFootArrowIv.startAnimation(footAnimation);// 启动动画
if (isEmpty(loadMoreLastUpdate)) {
mFootLastUpdateTv.setVisibility(View.GONE);
} else {
mFootLastUpdateTv.setVisibility(View.VISIBLE);
}
}
break;
// 加载状态
case LV_LOADING: {
Log.e("!!!!!!!!!!!", "convert to IListViewState.LVS_LOADING");
mFootProgressIv.setVisibility(View.VISIBLE);
mFootProgressIv.startAnimation(loadingAnimation);
mFootArrowIv.clearAnimation();
mFootArrowIv.setVisibility(View.GONE);
mFootRefreshTv.setText(R.string.loading);
if (isEmpty(loadMoreLastUpdate)) {
mFootLastUpdateTv.setVisibility(View.GONE);
} else {
mFootLastUpdateTv.setVisibility(View.VISIBLE);
}
}
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 (refreshListener != null && refresh) {
refreshListener.onRefresh();
}
}


/***
* 下拉刷新完毕
*/
public void onRefreshComplete() {
mHeadProgressIv.clearAnimation();
mRefreshTv.setText(R.string.refreshDone);
refreshLastUpdate = sdf.format(new Date());
mLastUpdateTv.setText(context.getString(R.string.lastUpdate) + ":"
+ refreshLastUpdate);// 修改更新后的界面时间
// 执行相应动画.
myAsynTask = new MyAsynTask();
myAsynTask.execute(HEAD_DOWN);
}


private void onLoadMore() {
if (loadMoreListener != null && loadMore && getAdapter().getCount() > 2) {
loadMoreListener.onLoadMore();
}
}


/***
* 下拉刷新完毕
*/
public void onLoadMoreComplete() {
mFootProgressIv.clearAnimation();
mFootRefreshTv.setText(R.string.loadMoreDone);
loadMoreLastUpdate = sdf.format(new Date());
mFootLastUpdateTv.setText(context.getString(R.string.lastUpdate) + ":"
+ loadMoreLastUpdate);// 修改更新后的界面时间
// 执行相应动画.
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) {
mHeadProgressIv.clearAnimation();
mRefreshTv.setText(R.string.refreshFail);
} else {
mFootProgressIv.clearAnimation();
mFootRefreshTv.setText(R.string.loadMoreFail);
}
// 执行相应动画.
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 OnRefreshListener {
void onRefresh();
}


public interface OnLoadMoreListener {
void onLoadMore();
}


public interface OnItemClickListener {
void onItemClick(int position, View child);
}


public interface onSlidListener {
void onSlid(int position, View child);
}


private boolean isEmpty(String str) {
if (str == null || str.trim().equals("")) {
return true;
}
return false;
}
}



布局文件:

<?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"
    android:background="@color/black" >


    <!-- 内容 -->


    <RelativeLayout
        android:id="@+id/head_contentLayout"
        android:layout_width="fill_parent"
        android:layout_height="50dp" >


        <!-- 箭头图像、进度条 -->


        <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/arrowIv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="@drawable/refresh" />


            <!-- 进度条 -->


            <ImageView
                android:id="@+id/progressIv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="@drawable/refresh"
                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/tipsTv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/white"
                android:textSize="14sp" />


            <!-- 最近更新 -->


            <TextView
                android:id="@+id/lastUpdateTv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/white"
                android:textSize="10sp"/>
        </LinearLayout>
    </RelativeLayout>
</LinearLayout>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值