自定义下拉刷新的listview
listview的下拉刷新功能的实现依靠在listview前面加上头布局,通过判断头布局的位置确实用户是否下拉,然后根据情况进行处理
1. 自定义一个类继承ListView
2. 自定义一个布局用于加入listView的头布局中
自定义的类代码如下:
public class ReflashListView extends ListView implements OnScrollListener {
private final static int PULL_To_REFRESH = 0; // 下拉的状态值
private final static int REFRESHING = 1;// 正在刷新的状态值
private final static int RELEASE_REFRESH = 2; // 松开刷新的状态值
private LayoutInflater mInflater;
private View mheardView;
private ImageView ivArrow;
private TextView tvTitle;
private TextView tvTime;
private ProgressBar pbProgress;
private int mhearderHeight; // 下拉刷新布局的高度
private boolean isreflash; // 是否可以下拉刷新
private int startY = -1;
private int state = PULL_To_REFRESH; // 记录当前状态
private Animation animUp;
private Animation animDown;
public ReflashListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initViews();
}
public ReflashListView(Context context, AttributeSet attrs) {
super(context, attrs);
initViews();
}
public ReflashListView(Context context) {
super(context);
initViews();
}
private void initViews() {
mInflater = LayoutInflater.from(getContext());
mheardView = mInflater.inflate(R.layout.list_reflash_heard_item, null);
this.addHeaderView(mheardView);
ivArrow = (ImageView) mheardView.findViewById(R.id.iv_arr);
tvTitle = (TextView) mheardView.findViewById(R.id.tv_title);
tvTime = (TextView) mheardView.findViewById(R.id.tv_date);
pbProgress = (ProgressBar) mheardView.findViewById(R.id.pb_progress);
measureView(mheardView);
mhearderHeight = mheardView.getMeasuredHeight();
Log.d("tag", "mhearderHeight:" + mhearderHeight);
topPadding(-mhearderHeight);
addHeaderView(mheardView, null, false);// 将下拉布局加入listView顶部
setOnScrollListener(this);
initArrowAnim();
}
/**
* 设置mheardView布局的上边距
*
* @param i
*/
private void topPadding(int i) {
mheardView.setPadding(mheardView.getPaddingLeft(), i,
mheardView.getPaddingRight(), mheardView.getPaddingBottom());
mheardView.invalidate(); // 重新绘制mheardView
}
/**
* 通知父布局headerView的尺寸(便于后面测量headerView的高度)
*
* @param child
*/
private void measureView(View child) {
ViewGroup.LayoutParams params = child.getLayoutParams();
if (params == null) {
params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
// 1.左右边距 2.内边距 3.子布局宽度
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);
int lpHeight = params.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (firstVisibleItem == 0) {
isreflash = true;
} else {
isreflash = false;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if (startY == -1) {// 确保startY有效
startY = (int) ev.getRawY();
}
if (state == REFRESHING) {// 正在刷新
break;
}
int tempY = (int) ev.getY();
int dy = tempY - startY; // 偏移量
Log.d("tag", "偏移量:" + dy);
if (dy > 0) {
int pading = dy - mhearderHeight;
topPadding(pading);
if (pading > 0 && state != RELEASE_REFRESH) {
state = RELEASE_REFRESH;
topPadding(0);
refreshState();
} else if (pading < 0 && state != PULL_To_REFRESH) {
state = PULL_To_REFRESH;
refreshState();
}
return true;
}
break;
case MotionEvent.ACTION_UP:
startY = -1;// 重置
if (state == RELEASE_REFRESH) {
state = REFRESHING;// 正在刷新
topPadding(0);
refreshState();
} else if (state == PULL_To_REFRESH) {
topPadding(-mhearderHeight);
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
/**
* 通过State值改变hearerView状态
*/
private void refreshState() {
switch (state) {
case PULL_To_REFRESH:
tvTitle.setText("下拉刷新");
ivArrow.setVisibility(View.VISIBLE);
pbProgress.setVisibility(View.INVISIBLE);
ivArrow.startAnimation(animDown);
break;
case RELEASE_REFRESH:
tvTitle.setText("松开刷新");
ivArrow.setVisibility(View.VISIBLE);
pbProgress.setVisibility(View.INVISIBLE);
ivArrow.startAnimation(animUp);
break;
case REFRESHING:
tvTitle.setText("正在刷新...");
ivArrow.clearAnimation();// 必须先清除动画,才能隐藏
ivArrow.setVisibility(View.INVISIBLE);
pbProgress.setVisibility(View.VISIBLE);
break;
default:
break;
}
}
/**
* 初始化箭头动画
*/
private void initArrowAnim() {
animUp = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
animUp.setDuration(200);
animUp.setFillAfter(true);
animDown = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animDown.setDuration(200);
animDown.setFillAfter(true);
}
}