1、 创建一个类继承一直ListView:class PullToRefreshListView extends ListView
2、 在构造方法中添加HeadView:addHeaderView(headView);
3、 获取HeadView的高:
自定义View常用的方法:onMeasure onLayout onDraw
1. getMeasuredHeight() 在onMeasure方法执行之后才能获取到,测量的高度
2. getHeight() 在onLayout方法执行之后才能获取到值,真实画的时候决定的高度
一般这两个方法所获取的值是相等的,但是其实是可以不相等的。
4、 隐藏headView:headView.setPadding(0, -headViewHeight, 0, 0);
5、 什么时候显示HeadView:当向下滑,且第一条可见item是第0条的时候才需要设置HeadView的paddingTop来显示HeadView
int fingerMoveDistanceY = (int) (ev.getY() - downY);
if (getFirstVisiblePosition() == 0 && fingerMoveDistanceY > 0) {
int paddingTop = fingerMoveDistanceY - headViewHeight;
setHeadViewPaddingTop(paddingTop);
return true; // 代表自己已经处理了这个事件,不需要使用ListView的事件了
}
6、 下拉刷新三种状态的判断
* 移动的时候,当paddingTop < 0
的时候,说明HeadView没有完全显示出来,进入下拉刷新状态:
if (paddingTop < 0 && currentState != STATE_PULL_TO_REFRESH) {
currentState = STATE_PULL_TO_REFRESH;
}
* 移动的时候,当paddingTop >= 0 的时候,说明HeadView已经完全显示出来了,进入松开以新状态:
if (paddingTop >= 0 && currentState != STATE_RELEASE_TO_REFRESH) {
currentState = STATE_RELEASE_TO_REFRESH;
}
* 手指抬起的时候,且当前状态是松开刷新状态的时候,进入正在刷新状态:
if (currentState == STATE_RELEASE_TO_REFRESH) {
currentState = STATE_REFRESHING;
}
* 当已经是“正在刷新”状态时,则不允许再做”下拉刷新”和”松开刷新”的操作了,在Move事件中加入如下判断:
case MotionEvent.ACTION_MOVE:
if (currentState == STATE_REFRESHING) {
// 如果已经是正在刷新状态了,则不处理下拉的操作了
return super.onTouchEvent(ev);
}
7、 下拉箭头的转动
往上转:0 ~ -180
往下转:-180 ~ -360
创建动画类:
private RotateAnimation createAnimator(float fromDegrees, float toDegrees) {
int pivotXType = RotateAnimation.RELATIVE_TO_SELF; // 设置旋转点X轴参照物
int pivotYType = RotateAnimation.RELATIVE_TO_SELF; // 设置旋转点Y轴参照物
float pivotXValue = 0.5f; // 设置旋转点X轴的位置为View的中心点
float pivotYValue = 0.5f; // 设置旋转点Y轴的位置为View的中心点
RotateAnimation ra = new RotateAnimation(fromDegrees, toDegrees, pivotXType,
pivotXValue, pivotYType, pivotYValue);
ra.setDuration(300); // 设置动画执行时间
ra.setFillAfter(true); // 设置动画保持在结束状态
return ra;
}
8、 隐藏箭头的时候要清除动画:iv_arrow.clearAnimation(); 如果不隐藏动画效果,设置View.GONE之后还是看得见的。
9、 HeadView显示时,当手指松开时的处理:
a) 松开时如果是“正在刷新”状态,则把headView完全显示
if (currentState == STATE_REFRESHING) {
showHeadView();
}
b) 松开时如果是“下拉刷新”状态,则把HeadView完全隐藏
if (currentState == STATE_PULL_TO_REFRESH) {
hideHeadView();
}
10、 增加FooterView:addFooterView(footerView);
11、 什么时候显示FooterView呢?当ListView处于空闲状态,并且最后一条可见item是ListView中的最后一条数据则显示:
private OnScrollListener mOnScrollListener = new OnScrollListener() {
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE // 是空闲状态
&& getLastVisiblePosition() == getCount() - 1 // 最后可见Item不是最后一条数据
&& !loadingMore) { // 没有做联网加载更多的事情
loadingMore = true;
showFooterView();
}
}
};
12、 FooterView显示出来后,ListView不会自动上滑把FooterView显示出来的,所以需要手动设置:setSelection(getCount() - 1);// 选中最后一条
增加回调监听器
public interface OnRefreshingLinstener {
/** 当ListView处于刷新状态的时候会调用 */
void onRefreshing();
/** 当ListView处于加载更多的时候会调用 */
void onLoadMore();
}