package com.orgcent.demo.view;
import java.lang.reflect.Field;
import java.util.List;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HeaderViewListAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import static com.orgcent.demo.view.UpRefreshListView.OnRefreshStatusListener.*;
/**
* 参考了另一篇文章思路:
* https://github.com/johannilsson/android-pulltorefresh
*
*/
public class UpRefreshListView extends ListView {
private OnRefreshStatusListener mStatusListener;
private View mRefreshView;
private TranslateHelper mTranslate;
private float mLastY;
private int mOldTopPadding = -1;
private static int MAX_TOP_PADDING ; //init()中初始化,单位像素
private int mRefreshStatus = STATUS_TOP_EDGE; //两种,
private boolean mRefreshViewAdded;
public UpRefreshListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public UpRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public UpRefreshListView(Context context) {
super(context);
init();
}
private void init() {
MAX_TOP_PADDING = dp2px(100);
}
private int dp2px(float dp) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
/**
* 设置顶部显示的加载界面
*
* 在setAdapter()之前设置
* @param headerView
*/
public void setRefreshView(View headerView) {
if(null != headerView) {
mRefreshView = headerView;
}
}
public void setRefreshView(int resId) {
View headerView = inflate(getContext(), resId, null);
setRefreshView(headerView);
}
/**
* 当数据加载完成后,调用此方法隐藏刷新视图
*/
public void hideRefreshView() {
final View headerView = mRefreshView;
if(null != headerView && mRefreshViewAdded) {
removeHeaderView(headerView);
mRefreshViewAdded = false;
}
}
@Override
public void setAdapter(ListAdapter adapter) {
final boolean needAdd = getHeaderViewsCount() == 0 && getFooterViewsCount() == 0;
if(needAdd) {
final View headerView = mRefreshView;
if(null != headerView && !mRefreshViewAdded) {
addHeaderView(headerView);
mRefreshViewAdded = true;
}
super.setAdapter(adapter);
if(null != headerView && mRefreshViewAdded) {
removeHeaderView(headerView);
mRefreshViewAdded = false;
}
} else {
super.setAdapter(adapter);
}
}
public OnRefreshStatusListener getStatusListener() {
return mStatusListener;
}
public void setStatusListener(OnRefreshStatusListener mStatusListener) {
this.mStatusListener = mStatusListener;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
final View view = mRefreshView;
if(-1 == mOldTopPadding && null != view) {
mOldTopPadding = view.getPaddingTop();
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {//列表位于顶端,再向上拉时才处理
if(null != mRefreshView && getFirstVisiblePosition() == 0 && ev.getEdgeFlags() == 0) {
processTouch(ev);
}
return super.onTouchEvent(ev);
}
private void processTouch(MotionEvent ev) {
int action = ev.getAction();
float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mLastY = y;
break;
case MotionEvent.ACTION_MOVE: {
int topPadding = (int) (y - mLastY) ;
if(0 > topPadding) {
topPadding = 0;
} else if(topPadding > MAX_TOP_PADDING) {
topPadding = MAX_TOP_PADDING;
}
final View headerView = mRefreshView;
if(!mRefreshViewAdded) { //下拉重新添加顶部刷新界面
mRefreshViewAdded = true;
addRefreshView(headerView);
}
int status = mRefreshStatus;
if(mStatusListener != null && status == STATUS_TOP_EDGE
&& topPadding >= MAX_TOP_PADDING / 2 //提前一半,开始显示刷新提示
&& null != headerView) {
mRefreshStatus = status = STATUS_BOTTOM_EDGE;
mStatusListener.onStatusChanaged(headerView, status);
}
topPadding += mOldTopPadding; //在原有padding基础上增加
setTopPadding(topPadding);
break;
}
case MotionEvent.ACTION_UP: { //抬起,匀速复原
if(null == mTranslate) {
final View v = mRefreshView;
final int end = mOldTopPadding, start = v.getPaddingTop();
if(start > 0) {
mTranslate = new TranslateHelper(start, end);
postDelayed(mTranslate, TranslateHelper.INTERVAL);
}
}
break;
}
default:
break;
}
}
private void addRefreshView(View v) {
boolean executed = false;
try {
Field f = getClass().getDeclaredField("mHeaderViewInfos");
if(null != f) {
Object obj = f.get(this);
if(obj instanceof java.util.List) {//绕开必须setAdapter()前添加HeaderView限制
List<FixedViewInfo> mHeaderViewInfos = (List<FixedViewInfo>) obj;
FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = null;
info.isSelectable = false;
mHeaderViewInfos.add(0,info); //添加刷新视图到HeaderView第一项
executed = true;
}
}
} catch (Exception e) {
// e.printStackTrace();
}
if(!executed) { //没有执行,将调用ListView提供的API
ListAdapter adapter = getAdapter();
if(adapter instanceof HeaderViewListAdapter) {
adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
}
super.setAdapter(null);
addHeaderView(v);
super.setAdapter(adapter);
}
}
public static interface OnRefreshStatusListener {
static final int STATUS_BOTTOM_EDGE = 1; //此时被完全拉起
static final int STATUS_TOP_EDGE = 0; //默认位置或拉起后恢复位置
void onStatusChanaged(View v, int status);
}
private class TranslateHelper implements Runnable {
int end, current;
int SPEED = 15; //移动速度
static final int INTERVAL = 10; //间隔时间(毫秒)
public TranslateHelper(int start, int end) {
this.end = end;
this.current = start;
SPEED = dp2px(SPEED);
}
@Override
public void run() {
current -= SPEED;
if(current < end) {
current = end;
}
setTopPadding(current);
if(current == end) {
removeCallbacks(this);
mTranslate = null;
final View headerView = mRefreshView;
int status = mRefreshStatus;
if(status == STATUS_BOTTOM_EDGE && mStatusListener != null
&& null != headerView) {
mRefreshStatus = status = STATUS_TOP_EDGE;
mStatusListener.onStatusChanaged(headerView, status);
}
} else {
postDelayed(this, INTERVAL);
}
}
}
private void setTopPadding(int topPadding) {
final View view = mRefreshView;
if(null != view) {
view.setPadding(view.getPaddingLeft(), topPadding, view.getPaddingRight(), view.getPaddingBottom());
}
}
}
- 1
- 2
- 3
前往页