通过自定义ListView控件实现下拉刷新功能。
public class RefreshListView extends ListView implements AbsListView.OnScrollListener {
private View headerView;//初始化头布局
private ProgressBar mProgressBar;//设置头布局的进度圈
private TextView tvState;//设置头布局的状态
private TextView tvLastUpdateTime;//设置头布局的最后刷新时间
private int headerViewHeight;//记录头布局的高度
private RotateAnimation upAnimation;
private RotateAnimation downAnimation;
private int downY;//按下时Y轴的偏移量
private final int DOWN_PULL = 0; // 头布局状态: 下拉刷新
private final int RELEASE_REFRESH = 1; // 头布局状态: 释放刷新
private final int REFRESHING = 2; // 头布局状态: 正在刷新中..
private int currentState = DOWN_PULL; // 头布局当前的状态, 默认为: 下拉刷新
private ImageView ivArrow; // 头布局的箭头
private OnRefreshListener refreshListener;//define OnRefreshListener
public RefreshListView(Context context) {
super(context);
initHeaderView();
//设置手指滑动的监听器
setOnScrollListener(this);
}
public RefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
initHeaderView();
}
/**
* 初始化listview头布局
*/
private void initHeaderView() {
headerView=View.inflate(getContext(), R.layout.listview_header, null);
//找到各个控件
ivArrow = (ImageView) headerView.findViewById(R.id.iv_listview_header_arrow);
mProgressBar = (ProgressBar) headerView.findViewById(R.id.pb_listview_header);
tvState = (TextView) headerView.findViewById(R.id.tv_listview_header_state);
tvLastUpdateTime = (TextView) headerView.findViewById(R.id.tv_listview_header_last_update_time);
tvLastUpdateTime.setText("最后刷新时间: " + getCurrentTime());
headerView.measure(0, 0);//都是0,说明让系统框架去测量头布局的 宽 高。
// headerView.getHeight()//此方法是和headview没有显示到屏幕上之前而调用的,一直都是0
headerViewHeight = headerView.getMeasuredHeight();//只有当measure方法被调用完毕后才可以得到具体高度
//隐藏头布局
headerView.setPadding(0,-headerViewHeight,0,0);
//向listview的顶部追加一个布局
this.addHeaderView(headerView);
//添加箭头反转的动画
initAnimation();
}
/**
* 初始化动画
*/
private void initAnimation() {
upAnimation=new RotateAnimation(0,-180,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(500);
upAnimation.setFillAfter(true);//让控件停止在动画结束的状态
downAnimation = new RotateAnimation(
-180, -360,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
downAnimation.setDuration(500);
downAnimation.setFillAfter(true); // 让控件停止在动画结束的状态下
}
/**
*用于日期格式化的方法
* @return
*/
private String getCurrentTime() {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
/**
* 手指滑动的事件
* @param ev
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
downY= (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveY= (int) ev.getY();
//间距
int diffY=moveY-downY;
int paddingTop=-headerViewHeight+diffY;
//获得第一个显示条目的索引
int firstVisiblePosition = getFirstVisiblePosition();
if(paddingTop>-headerViewHeight&&firstVisiblePosition==0){
if(paddingTop > 0 && currentState == DOWN_PULL) { // 头布局完全显示, 并且当前状态是下拉刷新, 进入到松开刷新的状态
System.out.println("松开刷新");
currentState = RELEASE_REFRESH;
refreshHeaderViewState();
} else if(paddingTop < 0 && currentState == RELEASE_REFRESH) { // 头布局没有完全显示, 并且当前状态是松开刷新, 进入到下拉刷新的状态
System.out.println("下拉刷新");
currentState = DOWN_PULL;
refreshHeaderViewState();
}
headerView.setPadding(0,paddingTop,0,0);//让头布局显示的关键方法
// return true;//自己处理用户触摸的滑动的事件
}
break;
case MotionEvent.ACTION_UP:
// 判断当前的状态是哪一种
if(currentState == DOWN_PULL) { // 当前是在下拉刷新状态下松开了, 什么都不做, 把头布局隐藏就可以.
headerView.setPadding(0, -headerViewHeight, 0, 0);
} else if(currentState == RELEASE_REFRESH) { // 当前的状态属于释放刷新, 并且松开了. 应该把头布局正常显示, 进入正在刷新中状态.
headerView.setPadding(0, 0, 0, 0);
currentState = REFRESHING;
refreshHeaderViewState();
/**
* 调用用户的监听事件
*/
if(refreshListener!=null){
refreshListener.onPullDownFresh();
}
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
/**
* 刷新头布局的状态
*/
private void refreshHeaderViewState() {
switch (currentState) {
case DOWN_PULL: // 下拉刷新
ivArrow.startAnimation(downAnimation);
tvState.setText("下拉刷新");
break;
case RELEASE_REFRESH: // 松开刷新
ivArrow.startAnimation(upAnimation);
tvState.setText("松开刷新");
break;
case REFRESHING: // 正在刷新中
ivArrow.clearAnimation(); // 把自己身上的动画清除掉
ivArrow.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
tvState.setText("正在刷新..");
break;
default:
break;
}
}
/**
* 刷新完成, 用户调用此方法, 把对应的头布局或脚布局给隐藏掉
*/
public void onRefreshFinish() {
// 隐藏头布局
headerView.setPadding(0, -headerViewHeight, 0, 0);
currentState = DOWN_PULL;
mProgressBar.setVisibility(View.INVISIBLE);
ivArrow.setVisibility(View.VISIBLE);
tvState.setText("下拉刷新");
tvLastUpdateTime.setText("最后刷新时间: " + getCurrentTime());
}
/**
* 提供者给使用者设置刷新的监听事件
* @param Listener
*/
public void setRefreshListenere(OnRefreshListener Listener){
refreshListener=Listener;
}
/**
* 定义一个接口,当listview刷新时的监听事件,用户可以实现此方法,在listview正在刷新时
*/
public interface OnRefreshListener{
/**
* 当下拉刷新时会掉此方法
*/
public void onPullDownFresh();
}
}