总结:下拉刷新是监控了ListView的onTouchEvent这个事件,计算滑动的距离,动态设置listview头部的padding,
header.setPadding立即:如果top是正值,那么top边就向上跑,形成一段空隙,如果top为负值,top边就向下跑,这样就湮没了头部的顶部,
其他情况类似,先理解正值往哪里跑,再理解负值,往反方向跑
还有一点设置padding可能会引起控件高度和宽度的变化的
package com.example.customview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* Created by dream on 2015/11/2.
*/
public class CustomListView extends ListView {
View header;
int viewHeight;
ProgressBar progressBar;
ImageView ivArror;
TextView tvState;
byte currentState;
public static final byte STATE_DONE = 0;
public static final byte STATE_PULL = 1;
public static final byte STATE_RELEASE = 2;
public static final byte STATE_REFRESHING = 3;
int downY;
OnRefreshListener onRefreshListener;
/**
*
* @param onRefreshListener
* 实现类
*/
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
this.onRefreshListener = onRefreshListener;
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
header = inflate(context,R.layout.listview_header,null);
this.addHeaderView(header);
progressBar = (ProgressBar) header.findViewById(R.id.progressBar);
ivArror = (ImageView) header.findViewById(R.id.iv_arrow);
tvState = (TextView) header.findViewById(R.id.tv_state);
//getHeight 要求控件必须显示在屏幕上
//没显示,先测量,再getMeasuredHeight
header.measure(0, 0);
viewHeight=header.getMeasuredHeight();
Log.i("viewHeight", "" + viewHeight);
header.setPadding(0, 0, 0, -viewHeight);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
try {
switch(action){
case MotionEvent.ACTION_DOWN:
if(this.currentState==STATE_DONE){
this.currentState=STATE_PULL;
this.downY = (int) ev.getY();
}
break;
case MotionEvent.ACTION_MOVE:
if(this.currentState==STATE_PULL){
int moveY = (int) ev.getY();
int top = -viewHeight + moveY- downY;
header.setPadding(0, 0, 0, top);
//动态设置header的padding(每次设置都从0,0,0,0 效果开始出发考虑变化)
if (moveY - downY > viewHeight) {
this.currentState = STATE_RELEASE;
tvState.setText("松开刷新");
}
}
break;
case MotionEvent.ACTION_UP:
int h = header.getMeasuredHeight();
if (this.currentState == STATE_RELEASE) {
this.currentState = STATE_REFRESHING;
tvState.setText("刷新中"+h);
ivArror.setVisibility(View.GONE);
progressBar.setVisibility(VISIBLE);
if (onRefreshListener != null) {
onRefreshListener.onRefresh(this);
}
}
break;
}
}catch(Exception e){
e.printStackTrace();
}
return super.onTouchEvent(ev);
}
public void refreshComplete() {
progressBar.setVisibility(View.GONE);
ivArror.setVisibility(View.VISIBLE);
tvState.setText("下拉刷新");
header.setPadding(0, -viewHeight, 0, 0);
this.currentState = STATE_DONE;
}
interface OnRefreshListener {
public void onRefresh(CustomListView customListView);
}
}