1:建立一个android项目工程
2:为listview的headview新建一个布局文件(这个布局文件的最外层不能使用相对布局,否则在代码中使用该布局问的measure会报错,目前还没有查出什么原因,有高三可以指点下哈)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/background_dark"
android:orientation="horizontal" >
<FrameLayout
android:id="@+id/fl_headerview"
android:layout_width="60dip"
android:layout_height="wrap_content"
android:layout_marginLeft="30dip"
>
<ImageView
android:id="@+id/arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/arrow"
/>
<ProgressBar
android:id="@+id/pb_refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
style="@android:attr/progressBarStyleSmallInverse"
/>
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerInParent="true"
>
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12dip"
android:textColor="@android:color/background_light"
android:text="下拉进行刷新"
/>
<TextView
android:id="@+id/tv_last_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/background_light"
android:textSize="12dip"
android:text="最后跟新时间"
/>
</LinearLayout>
</LinearLayout>
3:新建一个类继承ListView(奉上自定的ListView的代码吧)
package com.example.mylistview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.ProgressBar;
public class MyListView extends ListView implements OnScrollListener {
private static final String TAG = "MyListView";
private OnrefreshListener refreshListener;//监听刷新接口
private boolean isOnrefreshListener;//是否设置了刷新监听
private ImageView iv_arrow;
private ProgressBar pb;
private TextView tv_title;
private TextView tv_last_updatetime;
private int headerviewHeigth;
private RotateAnimation realseAnimation;//由下拉到释放动画 动画后箭头朝上
private RotateAnimation pullAnimation;//到下拉动画 动画后箭头朝下
private float startY;//记录开始接触屏幕时 Y的坐标
private boolean isRecoder=false;//startY时候记录过了
private boolean isFirstItem=false;//是否是listView的第一个条目
private float tempY;
private int state=DONE;//当前状态
private String lastdate="";
public final static int PULL=0;//下拉状态
public final static int RELEASE=1;//释放状态
public final static int REFERESHING=2;//正在刷新
public final static int DONE=4;//刷新完成状态
private View view;
private float ratio=3;
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init(context);
}
public MyListView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
LayoutInflater inflater=LayoutInflater.from(context);
view = inflater.inflate(R.layout.list_refresh_headerview, null);
//注意list_refresh_headerview的最外层布局 不能使relativeLayout 否则会在98行报错,百度差不错原因,希望有高手可以解析下哈
iv_arrow = (ImageView) view.findViewById(R.id.arrow);
pb = (ProgressBar) view.findViewById(R.id.pb_refresh);
tv_title = (TextView) view.findViewById(R.id.tv_title);
tv_last_updatetime =(TextView)view.findViewById(R.id.tv_last_update);
measureHeaderview(view);
headerviewHeigth=view.getMeasuredHeight();
view.setPadding(0,-1*headerviewHeigth, 0,0);//讲headview这样设置 它会隐藏在界面最上面看不见
view.invalidate();//让headview重新绘制
this.addHeaderView(view);
this.setOnScrollListener(this);
this.setCacheColorHint(0x00000000);
//为箭头旋转 初始化2个动画
realseAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f);
realseAnimation.setFillAfter(true);
realseAnimation.setDuration(200);
pullAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f);
pullAnimation.setFillAfter(true);
pullAnimation.setDuration(200);
}
//测量HeadView的高度
private void measureHeaderview(View view) {
ViewGroup.LayoutParams lp=view.getLayoutParams();
if(null==lp){
lp=new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childMeasureWidth = ViewGroup.getChildMeasureSpec(0, 0, lp.width);
int childMeasureHeight;
if(lp.height > 0){
childMeasureHeight = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);//适合、匹配
} else {
childMeasureHeight = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);//未指定
}
Log.i(TAG,"width:"+childMeasureWidth+" height:"+childMeasureHeight);
view.measure(childMeasureWidth,childMeasureHeight);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(isFirstItem&&!isRecoder){
startY = event.getY();
isRecoder=true;
}
break;
case MotionEvent.ACTION_MOVE:
if(isFirstItem&&!isRecoder){
startY = event.getY();
isRecoder=true;
}
tempY = event.getY();
if(state!=REFERESHING&&isOnrefreshListener){//如果当前状态没有在刷新状态
view.setPadding(0,(int) ((tempY-startY)/ratio-headerviewHeigth), 0,0);
if(state==PULL){
if((tempY-startY)/ratio<headerviewHeigth&&(tempY-startY)>0){
//不用处理
}if((tempY-startY)/ratio>headerviewHeigth){
state=RELEASE;
dealState(state);
}if(tempY-startY<0){
state=DONE;
dealState(state);
}
}if(state==RELEASE){
if((tempY-startY)/ratio<headerviewHeigth&&(tempY-startY)>0){
//不用处理
state=PULL;
dealState(state);
}if((tempY-startY)/ratio>headerviewHeigth){
}if(tempY-startY<0){
state=DONE;
dealState(state);
}
}if(state==DONE){
if((tempY-startY)/ratio<headerviewHeigth&&(tempY-startY)>0){
//不用处理
state=PULL;
dealState(state);
}if((tempY-startY)/ratio>headerviewHeigth){
state=RELEASE;
dealState(state);
}if(tempY-startY<0){
}
}
}
break;
case MotionEvent.ACTION_UP:
if (state==RELEASE) {
state=REFERESHING;
dealState(state);
break;
}if(state==PULL){
state=DONE;
dealState(state);
break;
}
break;
}
return super.onTouchEvent(event);
}
/**
* 根据状态 做相关的处理
* @param state
*/
public void dealState(int state){
switch (state) {
case PULL:
pb.setVisibility(View.GONE);
iv_arrow.setVisibility(View.VISIBLE);
tv_title.setText("下拉进行刷新");
tv_last_updatetime.setVisibility(View.GONE);
iv_arrow.clearAnimation();
iv_arrow.startAnimation(realseAnimation);
break;
case RELEASE:
pb.setVisibility(View.GONE);
iv_arrow.setVisibility(View.VISIBLE);
tv_last_updatetime.setVisibility(View.GONE);
tv_title.setText("释放进行刷新");
iv_arrow.clearAnimation();
iv_arrow.startAnimation(pullAnimation);
break;
case REFERESHING:
pb.setVisibility(View.VISIBLE);
iv_arrow.clearAnimation();
iv_arrow.setVisibility(View.GONE);
tv_title.setVisibility(View.VISIBLE);
tv_title.setText("正在刷新...");
tv_last_updatetime.setText(lastdate);
tv_last_updatetime.setVisibility(View.VISIBLE);
view.setPadding(0,0,0,0);
refresh_();//获取数据
break;
case DONE:
pb.setVisibility(View.GONE);
iv_arrow.clearAnimation();
iv_arrow.setVisibility(View.VISIBLE);
tv_title.setText("下拉进行刷新");
tv_last_updatetime.setVisibility(View.GONE);
view.setPadding(0,-1*headerviewHeigth, 0,0);
break;
}
}
@Override
public void onScroll(AbsListView ablistview,int firstVisibleItem,int visibleItemCount,int totalItemCount){
Log.i(TAG,"firstVisibleItem:"+firstVisibleItem+"visibleItemCount:"+visibleItemCount+"totalItemCount:"+totalItemCount);
if(firstVisibleItem==0){
isFirstItem=true;//如果listview的第一个条目 才给设置成true,才有下来刷新
}else{
isFirstItem=false;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
/**
* 对listview刷新监听
* @author janecer
*/
public interface OnrefreshListener{
void refresh();
}
public void refresh_(){
refreshListener.refresh();
isRecoder=false;
}
public void setOnrefreshListener(OnrefreshListener refreshlisttener){
refreshListener = refreshlisttener;
isOnrefreshListener = true;
}
/**
* 刷新完成
*/
public void onRefreshComplete(){
state=DONE;
lastdate=""+new java.util.Date().getTime();
view.setPadding(0,-1*headerviewHeigth,0,0);
dealState(state);
}
}
4:在MainActivity的布局文件如下
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.example.mylistview.MyListView
android:id="@+id/lv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
5:在MainActivity里面使用自定义的ListView 如下
package com.example.mylistview;
import java.util.ArrayList;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class MainActivity extends Activity {
private ListViewAdapter adapter;
private MyListView listview;
private ArrayList<String> items;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化4个数据显示在Listview上
items = new ArrayList<String>();
for (int i = 0; i <4; i++) {
items.add("______"+i);
}
listview = (MyListView) findViewById(R.id.lv);//这里需要强转为MyListView,不能使ListView
adapter = new ListViewAdapter();
listview.setAdapter(adapter);
listview.setOnrefreshListener(new MyListView.OnrefreshListener() {
@Override
public void refresh() {
new AsyncTask<Void,Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(2000);
items.add("刷新后新增的数据");
return null;
}
protected void onPostExecute(Void result) {
adapter.notifyDataSetChanged();
listview.onRefreshComplete();
};
}.execute();
}
});
}
private class ListViewAdapter extends BaseAdapter{
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int arg0) {
return null;
}
@Override
public long getItemId(int arg0) {
return arg0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv=new TextView(MainActivity.this);
tv.setText("aaa+"+items.get(position));
return tv;
}
}
}
Ok 搞定!希望可以帮到大家,谢谢!
http://download.csdn.net/detail/janecer/6882471 这是自定义listview源码下载地址,大家可以先下载下来看下效果