public class RefreshListView extends ListView {
private HeaderHelper mHeaderHelper;
private float lastY;
private float lastX;
private FooterHelper mFooterHelper;
private Transform currentHelper;
public RefreshListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RefreshListView(Context context) {
super(context);
init();
}
public void setLoadMore(boolean b) {
mFooterHelper.setEnabled(b);
}
public boolean isFree() {
return !mHeaderHelper.isRefresh() && !mFooterHelper.isLoadingMore();
}
private void init() {
initValueAnimator();
mHeaderHelper = new HeaderHelper();
mFooterHelper = new FooterHelper();
mHandler = new Handler();
setOverScrollMode(OVER_SCROLL_NEVER);
}
private void startAnimator(Transform helper, int current, int target) {
this.currentHelper = helper;
mAnim.setIntValues(current, target);
mAnim.start();
}
private void initValueAnimator() {
mAnim = new ValueAnimator();
mAnim.addUpdateListener(new AnimatorUpdateListener() { // 监听值的变化
public void onAnimationUpdate(ValueAnimator animator) {
int value = (Integer) animator.getAnimatedValue();// 运行当前时间点的一个值
if (currentHelper != null) {
currentHelper.setPaddingTop(value);
}
}
});
mAnim.addListener(new AnimatorListener() {
public void onAnimationStart(Animator animation) {
}
public void onAnimationRepeat(Animator animation) {
}
public void onAnimationEnd(Animator animation) {
if (currentHelper != null) {
currentHelper.finish();
currentHelper = null;
}
}
public void onAnimationCancel(Animator animation) {
}
});
mAnim.setDuration(250);
}
boolean mRefreshVisable = false;
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mRefreshVisable = false;
lastY = ev.getRawY();
lastX = ev.getRawX();
break;
case MotionEvent.ACTION_MOVE:
if (Math.abs(ev.getRawY() - lastY) > Math.abs(ev.getRawX() - lastX)
&& mHeaderHelper.offset(ev.getRawY() - lastY)) {
mRefreshVisable = true;
lastY = ev.getRawY();
lastX = ev.getRawX();
return true;
} else if (mRefreshVisable) {
mRefreshVisable = false;
ev.setAction(MotionEvent.ACTION_CANCEL);
}
lastY = ev.getRawY();
lastX = ev.getRawX();
break;
case MotionEvent.ACTION_UP:
mHeaderHelper.offsetComplete();
if (mRefreshVisable) {
mRefreshVisable = false;
ev.setAction(MotionEvent.ACTION_CANCEL);
}
break;
case MotionEvent.ACTION_CANCEL:
mHeaderHelper.offsetComplete();
break;
}
try {
return super.onTouchEvent(ev);
} catch (Exception e) {
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = ev.getRawY();
lastX = ev.getRawX();
break;
}
return super.onInterceptTouchEvent(ev);
}
private OnRefreshListener listener;
private Handler mHandler;
private ValueAnimator mAnim;
public void setOnRefreshListener(OnRefreshListener listener) {
this.listener = listener;
}
public static interface OnRefreshListener {
void onPullRefresh();
void onLoadingMore();
}
public void complete() {
boolean isChange = false;
if (mHeaderHelper.isRefresh()) {
mHeaderHelper.completeRefresh();
isChange = true;
}
if (mFooterHelper.isLoadingMore()) {
mFooterHelper.completeLoadingMore();
isChange = true;
}
if (isChange)
invalidateViews();
}
private class HeaderHelper implements Transform {
/**
* 下拉刷新的状态
*/
final int PULL_REFRESH = 0;
/**
* 松开刷新的状态
*/
final int RELEASE_REFRESH = 1;
/**
* 正在刷新的状态
*/
final int REFRESHING = 2;
int currentState;
private View header;
private int headerHeight;
private RotateAnimation upAnimation;
private RotateAnimation downAnimation;
private int currentPaddingTop;
private View arrow;
private View progress;
private TextView hint;
private TextView time;
Runnable r;
private long pullRefreshTimeMillis;
HeaderHelper() {
r = new Runnable() {
public void run() {
currentState = PULL_REFRESH;
// setPaddingTop(-headerHeight);
startAnimator(HeaderHelper.this, currentPaddingTop,
-headerHeight);
}
};
header = View.inflate(getContext(), R.layout.refreshable_header,
null);
header.measure(0, 0);
headerHeight = header.getMeasuredHeight();
setPaddingTop(-headerHeight);
addHeaderView(header);
currentState = PULL_REFRESH;
initRotateAnimation();
arrow = header.findViewById(R.id.arrow);
progress = header.findViewById(R.id.progress);
hint = (TextView) header.findViewById(R.id.hint);
time = (TextView) header.findViewById(R.id.data);
}
public void setPaddingTop(int top) {
if(top<-headerHeight)top = -headerHeight;
this.currentPaddingTop = top;
header.setPadding(0, top, 0, 0);
}
/**
* 返回true 时表示将要消耗此次事件
*
* @param dy
* @return
*/
boolean offset(float dy) {
if (isOffsetable()) {
setPaddingTop((int) (currentPaddingTop+dy*0.5f));
if (currentPaddingTop > 0 && currentState != RELEASE_REFRESH) {
currentState = RELEASE_REFRESH;
refreshViewForState();
} else if (currentPaddingTop <= 0
&& currentState != PULL_REFRESH) {
currentState = PULL_REFRESH;
refreshViewForState();
}
return true;
}
return false;
}
/**
* 在onTouchUp时调用
*/
void offsetComplete() {
if (isOffsetable()) {
if (currentPaddingTop > 0) {
currentState = REFRESHING;
// setPaddingTop(0);
startAnimator(this, currentPaddingTop, 0);
if (listener != null) {
listener.onPullRefresh();
pullRefreshTimeMillis = System.currentTimeMillis();
}
} else {
// setPaddingTop(-headerHeight);
startAnimator(this, currentPaddingTop, -headerHeight);
}
refreshViewForState();
}
}
void completeRefresh() {
mHandler.postDelayed(new Runnable() {
public void run() {
hint.setText("刷新完成");
time.setText("最后更新时间:" + getCurrentTime());
progress.setVisibility(View.INVISIBLE);
mHandler.postDelayed(r, 1000);
}
}, getDelayed());
}
long getDelayed() {
return Math
.max(0,
1500 - (System.currentTimeMillis() - pullRefreshTimeMillis));
}
private CharSequence getCurrentTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
Locale.CHINA);
return sdf.format(new Date());
}
/**
* 是否可以调整headerView
*
* @param dy
* @return
*/
boolean isOffsetable() {
return isFree() && currentState != REFRESHING
&& !canScrollVertically(-1);
}
void refreshViewForState() {
switch (currentState) {
case PULL_REFRESH:
hint.setText("下拉刷新");
arrow.setVisibility(View.VISIBLE);
arrow.startAnimation(downAnimation);
break;
case RELEASE_REFRESH:
arrow.setVisibility(View.VISIBLE);
hint.setText("释放刷新");
arrow.startAnimation(upAnimation);
break;
case REFRESHING:
hint.setText("正在刷新");
arrow.clearAnimation();
arrow.setVisibility(View.INVISIBLE);
progress.setVisibility(View.VISIBLE);
break;
}
}
boolean isRefresh() {
return currentState == REFRESHING;
}
void initRotateAnimation() {
upAnimation = new RotateAnimation(0, -180,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(100);
upAnimation.setFillAfter(true);
downAnimation = new RotateAnimation(-180, -360,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
downAnimation.setDuration(100);
downAnimation.setFillAfter(true);
}
@Override
public void finish() {
refreshViewForState();
}
}
private class FooterHelper implements OnScrollListener, Transform,
OnClickListener {
boolean mLoading;
private View footer;
private int footerHeight;
Runnable r;
private TextView tv;
private View progress;
private long loadingMoreTimeMillis;
private boolean mEnabled = false;
FooterHelper() {
r = new Runnable() {
public void run() {
mLoading = false;
// setPaddingTop(-footerHeight);
startAnimator(FooterHelper.this, 0, -footerHeight);
}
};
mLoading = false;
footer = View.inflate(getContext(), R.layout.refreshable_footer,
null);
footer.setOnClickListener(this);
tv = (TextView) footer.findViewById(R.id.tv);
progress = footer.findViewById(R.id.progress);
progress.setVisibility(View.INVISIBLE);
footer.measure(0, 0);
footerHeight = footer.getMeasuredHeight();
addFooterView(footer);
if (!mEnabled)
setPaddingTop(-footerHeight);
setOnScrollListener(this);
}
public void setEnabled(boolean b) {
if (mEnabled == b)
return;
mEnabled = b;
if (mEnabled) {
setPaddingTop(0);
} else {
setPaddingTop(-footerHeight);
}
}
boolean isLoadingMore() {
return mLoading;
}
public void setPaddingTop(int top) {
footer.setPadding(0, top, 0, 0);
}
void completeLoadingMore() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
tv.setText("加载完成");
progress.setVisibility(View.INVISIBLE);
mHandler.postDelayed(r, 1000);
}
}, getDelayed());
}
long getDelayed() {
return Math
.max(0,
1500 - (System.currentTimeMillis() - loadingMoreTimeMillis));
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
&& getLastVisiblePosition() == (getCount() - 1)) {
loadMore();
}
}
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
@Override
public void finish() {
setPaddingTop(0);
if (!mLoading) {
tv.setText("加载更多...");
}
}
@Override
public void onClick(View v) {
loadMore();
}
private void loadMore() {
if (mLoading || !isFree() || !mEnabled)
return;
mLoading = true;
// startAnimator(this, -footerHeight, 0);
// postDelayed(r2, 50);
setSelection(getCount());
if (listener != null) {
listener.onLoadingMore();
progress.setVisibility(View.VISIBLE);
tv.setText("正在加载……");
loadingMoreTimeMillis = System.currentTimeMillis();
}
}
}
private interface Transform {
void setPaddingTop(int top);
void finish();
}
}
转载于:https://my.oschina.net/SSS555/blog/838545