使用ListView实现下拉刷新效果

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源码下载地址,大家可以先下载下来看下效果

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值