自定义ListView实现下拉刷新流程以及思路
前言:全局变量以及参数说明 (以及在刷新之后的接口回调说明)
public class PullRefresh extends ListView {
private static final int STATE_PULL_REFRESH = 0; //下拉刷新状态
private static final int STATE_RELEASE_REFRESH = 1; //松开刷新的状态
private static final int STATE_REFRESHING_REFRESH = 2; //正在刷新
private OnRefreshListener onRefreshListener; //回调接口
private int CurrentStateCode = STATE_PULL_REFRESH; //当前状态
private View headView; //头部布局文件
private int measuredHeight, startY; //测量高度 && 初次点击坐标
private RotateAnimation imageAnimaRotate, imageAnimaReset; // 旋转动画 && 还原动画
接口回调方法:
//接口回调方法
public void onRefreshComplate(){
CurrentStateCode = STATE_PULL_REFRESH;
headView.setPadding(0,-measuredHeight,0,0); //重新设置内边距
}
下拉刷新是否回调判断以及刷新状态展示
public void refresh() {
switch (CurrentStateCode) {
case STATE_PULL_REFRESH:
pullPreImg.setVisibility(View.VISIBLE);
pullNextImg.setVisibility(View.GONE);
pullTv.setText("下拉刷新");
pullPreImg.startAnimation(imageAnimaReset);
break;
case STATE_RELEASE_REFRESH:
pullPreImg.setVisibility(View.VISIBLE);
pullNextImg.setVisibility(View.GONE);
pullTv.setText("释放刷新");
pullPreImg.startAnimation(imageAnimaRotate);
break;
case STATE_REFRESHING_REFRESH:
pullPreImg.setVisibility(View.GONE);
pullNextImg.setVisibility(View.VISIBLE);
pullTv.setText("正在刷新");
pullPreImg.clearAnimation();
if(onRefreshListener != null){
onRefreshListener.refreshData(); //回调
}
break;
}
}
1.下拉刷新状态 STATE_PULL_REFRESH (0 )
-
手指点击屏幕时触发MotionEvent.ACTION_DOWN(按下)事件
- 在此事件中,获取当前位置坐标,并且保存记录
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
...
return true;
case MotionEvent.ACTION_UP:
...
break;
}
return super.onTouchEvent(ev);
}
2.释放刷新状态 STATE_RELEASE_REFRESH (1)
-
手指滑动下拉刷新的过程中,触发MotionEvent.ACTION_MOVE(移动)事件,在此事件中需要做很多处理和判断
- 1.判断是否是 正在刷新 状态 (如果是,下次滑动则不会生效)
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
...
case MotionEvent.ACTION_MOVE:
if (startY == -1) {
startY = (int) ev.getY();
}
if (CurrentStateCode == STATE_REFRESHING_REFRESH) {
break;
}
...
return true;
case MotionEvent.ACTION_UP:
...
break;
}
return super.onTouchEvent(ev);
}
2.判断手指最后处于屏幕的距离与初次处于屏幕的距离只差是否为正数 并且当前状态是否处于 释放刷新 状态 ( 设置状态)
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
...
case MotionEvent.ACTION_MOVE:
...
int endY = (int) ev.getRawY();
int des = endY - startY;
if (des > 0 && CurrentStateCode != STATE_RELEASE_REFRESH)
{
CurrentStateCode = STATE_RELEASE_REFRESH;
headView.setPadding(0, des, 0, 0); //内边距
refresh();
}
return true;
case MotionEvent.ACTION_UP:
...
break;
}
return super.onTouchEvent(ev);
}
3.判断手指最后处于屏幕的距离与初次处于屏幕的距离只差是否为负数并且当前状态是否处于 **下拉刷新** 状态
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
...
case MotionEvent.ACTION_MOVE:
...
//接着判断
else if (des < 0 && CurrentStateCode != STATE_PULL_REFRESH) {
CurrentStateCode = STATE_PULL_REFRESH;
refresh();
}
return true;
case MotionEvent.ACTION_UP:
...
break;
}
return super.onTouchEvent(ev);
}
4.设置事件拦截,消费事件,不交给系统处理,自己处理。(在滑动事件直接return true)
case MotionEvent.ACTION_MOVE:
...
return true;
3.正在刷新 STATE_REFRESHING_REFRESH (2)
-
手指在抬起的时候触发 MotionEvent.ACTION_UP(抬起)事件
- 1.将初始化值设置为-1
- 2.判断当前状态是否为正在刷新状态
- 3.如果当前状态不是正在刷新 , 判断当前状态是否为下拉刷新状态 , 重新设置内边距
case MotionEvent.ACTION_UP:
startY = -1;
if (CurrentStateCode == STATE_RELEASE_REFRESH) {
CurrentStateCode = STATE_REFRESHING_REFRESH;
refresh();
} else if (CurrentStateCode == STATE_PULL_REFRESH) {
headView.setPadding(0, -measuredHeight, 0, 0);
refresh();
}
break;
4.回调接口(OnRefreshListener)
public interface OnRefreshListener {
void refreshData();
}
在主函数中
...
mySelfListView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void refreshData() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
... //更新数据操作
mySelfListView.onRefreshComplate(); //回调方法
}
},2000); //模拟两秒请求
}
});
...
总结
下拉刷新整个过程其实就是分为三步:点击、滑动、松开,只要将三个状态过程弄清楚,实现简单的下拉刷新便变得没那么复杂啦
源码已上传GitHub(https://github.com/NoMessages/PullRefresh-Blog)