上一节,其实有个坑~不知道大家有木有发现哈,没有好好理解的童鞋可能没有发现。那就是BannerAdapter中的getCount方法,我返回的是100,但是明显100是不可以滴。到100之后,他就不能再进行轮播了!所以需要把100 改成Integer.MAX_VALUE;
接下来就是另一个常用控件:PullToRefreshListView。这玩意虽然用起来挺简单,但是里面涉及的内容还是挺多的。例如:动画,listview的属性,listview的状态的切换,事件分发机制等。
让我们先来想一下大体的思路:
1.下拉刷新和上拉加载出来的控件,肯定是自定义的!那我们先写出来这两个控件
2.这个控件肯定不需要自己完全的自定义,所以肯定是需要继承ListView的
(1) 先写出HeaderView的控件
public HeaderView(Context context) {
super(context);
init(context);
}
public HeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
headerView = LayoutInflater.from(context).inflate(R.layout.layout_header,null);
addView(headerView);
mContentView = headerView.findViewById(R.id.ll_footer_content);
iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
pb_rotate = (ProgressBar) headerView.findViewById(R.id.pb_rotate);
tv_state = (TextView) headerView.findViewById(R.id.tv_state);
tv_time = (TextView) headerView.findViewById(R.id.tv_time);
}
(二)在ListView中,把HeaderView添加进去
private void initHeadView(Context context) {
headerView = new HeaderView(context);
//主动测量HeaderView
headerView.measure(0,0);
headHeight = headerView.getMeasuredHeight();
//通过设置padding来隐藏headerView
headerView.setPadding(0, -headHeight, 0, 0);
addHeaderView(headerView);
}
(三)既然都已经添加进去了,并且是默认的隐藏的状态,那么我们肯定会通过手指的滑动来进行刷新,所以需要复写onTouchEvent,来对手指进行监听
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
startY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
moveY = ev.getY();
//得出手指滑动的差值
detailY = moveY - startY;
int paddingTop = (int) (detailY -headHeight);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return super.onTouchEvent(ev);
}
(四)监听滑动了,然后呢?然后当然就是加载状态的改变啦,我们可以根据滑动的距离来判断
下拉刷新,松开刷新
//当是下拉的时候
if(paddingTop>=-headHeight){
headerView.setPadding(0,paddingTop,0,0);
if(paddingTop>0){
//当下拉的距离超出headview的高度的时候,进入了松开刷新状态
currentState = RELEASE_REFRESH;
refreshHeaderView();
}else{
//进入下拉刷新状态
currentState = PULL_REFRESH;
refreshHeaderView();
}
}
private void refreshHeaderView() {
switch (currentState){
case PULL_REFRESH:
headerView.pull_refresh();
break;
case RELEASE_REFRESH:
headerView.release_refresh();
break;
case REFRESHING:
headerView.refresh();
break;
}
}
(五)当手抬起来的时候,我们就需要判断抬手的时候,listview的状态是什么
if(currentState == PULL_REFRESH){
//隐藏headview
headerView.setPadding(0,-headHeight,0,0);
}else if(currentState == RELEASE_REFRESH){
headerView.setPadding(0,0,0,0);
currentState = REFRESHING;
refreshHeaderView();
}
(六)这样就可以实现基本的下拉刷新了。但是还有很多功能需要完善,比如,下拉有长度限制吗?
正在刷新的时候可以下拉吗?这些就需要完善了
(七)我们的需求是正在刷新的时候需要做网络请求,这就需要定义一个接口了
public void setOnRefreshChangeListener(onRefreshChangeListener listener){
this.listener = listener;
}
public interface onRefreshChangeListener{
void onPullRefresh();
}
在当状态变成正在刷新的时候调用onPullRefresh这个方法就行了
(八)当网络请求完成之后,我们就需要把正在刷新这个状态改变。所以再添加一个onCompleteRefresh方法,重置状态。这样下拉刷新基本上就完成了!
(九)下面来说上拉加载
上拉加载就简单多啦,那我们怎么判断什么时候出现FootView呢?当然是滑动到listview的底部的时候
setOnScrollListener(this);
/**
* SCROLL_STATE_IDLE:闲置状态,就是手指松开
* SCROLL_STATE_TOUCH_SCROLL:手指触摸滑动,就是按着来滑动
* SCROLL_STATE_FLING:快速滑动后松开
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//滑动到底部
if(scrollState == OnScrollListener.SCROLL_STATE_IDLE && getLastVisiblePosition() == this.getCount() -1 && !isLoadingMore ){
isLoadingMore =true;
footView.setPadding(0,0,0,0);
setSelection(getCount());
if(listener != null){
listener.onLoadMore();
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
这样就可以啦