public class PullToRefreshListView extends ListView implements OnScrollListener
{
private static final String TAG = "PullToRefreshListView";
/**
*顶部布局
*/
private View mHeaderView;
/**
* header的高度
*/
private int mHeaderHeight;
/**
* 当前页面已经滑到顶部
*/
private boolean flag;
/**
* 初始滑动时的y坐标
*/
private int mStartY;
/**
* 正常状态
*/
public static final int STATE_NORMAL = 0;
/**
* 下拉刷新状态
*/
public static final int STATE_PULL_TO_REFRESH = 1;
/**
* 释放刷新状态
*/
public static final int STATE_RELEASE_TO_REFRESH = 2;
/**
* 正在刷新状态
*/
public static final int STATE_REFRESH = 3;
/**
* 当前状态
*/
private int mCurrentState;
private static final int DEFAULT_LENGTH = 70;
private OnRefreshListener mRefreshListener;
public PullToRefreshListView(Context context, AttributeSet attrs,
int defStyle)
{
super(context, attrs, defStyle);
init(context);
}
public PullToRefreshListView(Context context, AttributeSet attrs)
{
super(context, attrs);
init(context);
}
public PullToRefreshListView(Context context)
{
super(context);
init(context);
}
public void setOnRefreshListener(OnRefreshListener listener)
{
this.mRefreshListener = listener;
}
/**
* 初始化操作
* @param context
*/
private void init(Context context)
{
//添加headerview
mHeaderView = LayoutInflater.from(context).inflate(R.layout.header_layout,null);
this.addHeaderView(mHeaderView);
//设置滚动监听器
this.setOnScrollListener(this);
//通过设置padding将hider隐藏
//注:因为此时无法获得header的高度,所以放入MessageQueue中
post(new HideHeaderAction());
}
/**
* 设置header的padding
* @param topPadding
*/
private void setHeaderTopPadding(int topPadding)
{
if(mHeaderView != null)
{
mHeaderView.setPadding(mHeaderView.getPaddingLeft(),topPadding,mHeaderView.getPaddingRight(),mHeaderView.getPaddingBottom());
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount)
{
if(firstVisibleItem == 0)
flag = true;
else
flag = false;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
}
@Override
public boolean onTouchEvent(MotionEvent ev)
{
int action = ev.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
if(flag)
{
mStartY = (int) ev.getY();
}
break;
case MotionEvent.ACTION_MOVE:
performMove(ev);
break;
case MotionEvent.ACTION_UP:
if(mCurrentState == STATE_RELEASE_TO_REFRESH)
{
mCurrentState = STATE_REFRESH;
updateUIByState();
//TODO 加载新数据
if(mRefreshListener == null)
{
throw new RuntimeException("you must call setOnRefreshListener before...");
}else
{
mRefreshListener.onRefresh(this);
}
}else if(mCurrentState == STATE_PULL_TO_REFRESH)
{
mCurrentState = STATE_NORMAL;
flag = false;
updateUIByState();
}
break;
}
return super.onTouchEvent(ev);
}
private void updateUIByState()
{
TextView tip = (TextView) findViewById(R.id.tip);
ImageView arrow = (ImageView) findViewById(R.id.arrow);
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress);
Animation anim1 = AnimationUtils.loadAnimation(getContext(),R.anim.rotate_1);
Animation anim2 = AnimationUtils.loadAnimation(getContext(),R.anim.rotate_2);
switch (mCurrentState)
{
case STATE_NORMAL:
setHeaderTopPadding(-mHeaderHeight);
break;
case STATE_PULL_TO_REFRESH:
arrow.clearAnimation();
arrow.setAnimation(anim1);
arrow.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
tip.setText("下拉可以刷新...");
break;
case STATE_RELEASE_TO_REFRESH:
arrow.clearAnimation();
arrow.setAnimation(anim2);
arrow.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
tip.setText("松开可以刷新...");
break;
case STATE_REFRESH:
arrow.clearAnimation();
setHeaderTopPadding(mHeaderHeight);
arrow.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
tip.setText("正在刷新...");
break;
default:
break;
}
}
private void performMove(MotionEvent ev)
{
if(!flag)
{
return;
}
int currY = (int) ev.getY();
int deltaY = currY-mStartY;
if(deltaY > mHeaderHeight+DEFAULT_LENGTH)
deltaY = mHeaderHeight+DEFAULT_LENGTH;
switch (mCurrentState)
{
case STATE_NORMAL:
if(deltaY > 0)
{
mCurrentState = STATE_PULL_TO_REFRESH;
}
break;
case STATE_PULL_TO_REFRESH:
setHeaderTopPadding(deltaY-mHeaderHeight);
updateUIByState();
if(deltaY >= mHeaderHeight+DEFAULT_LENGTH)
{
mCurrentState = STATE_RELEASE_TO_REFRESH;
}else if(deltaY <= 0)
{
mCurrentState = STATE_NORMAL;
}
break;
case STATE_RELEASE_TO_REFRESH:
// setHeaderTopPadding(deltaY-mHeaderHeight);
updateUIByState();
if(deltaY < mHeaderHeight+DEFAULT_LENGTH)
{
mCurrentState = STATE_PULL_TO_REFRESH;
}else if(deltaY <= 0)
{
mCurrentState = STATE_NORMAL;
}
break;
}
}
/**
* 更新完毕时调用
*/
public void refreshComplete()
{
TextView lastUpdateTime = (TextView) findViewById(R.id.last_update_time);
SimpleDateFormat format = new SimpleDateFormat("MM-dd hh:mm",Locale.CHINA);
String updateTime = format.format(new Date(System.currentTimeMillis()));
lastUpdateTime.setText("更新于 "+updateTime);
mCurrentState = STATE_NORMAL;
updateUIByState();
}
public interface OnRefreshListener
{
public void onRefresh(PullToRefreshListView listView);
}
private class HideHeaderAction implements Runnable
{
@Override
public void run()
{
//获取header的高度
mHeaderHeight = mHeaderView.getMeasuredHeight();//view在被渲染前无法获得其宽高
Log.d(TAG,"Headerheight:"+mHeaderHeight);
//通过设置header的padding来隐藏header
setHeaderTopPadding(-mHeaderHeight);
}
}
} |
|