现在的位置: 首页 > 综合 > 正文

UI_Android中实现ListView下拉刷新

2013年10月26日 ⁄ 综合 ⁄ 共 8736字 ⁄ 字号 评论关闭
package com.smiling.pulltorefreshlistview;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.MeasureSpec;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;

//自定义ListView类;

public class MyListView extends ListView implements OnScrollListener{
	                //States;
	private final static int PULL_TO_REFRESH=1;
	private final static int RELEASE_TO_REFRESH=2;
	private final static int LOADING=3;
	private final static int DONE=4;
	                          //比率;
	private final static int RATE=2;
	private int toTop=0;
	private LayoutInflater inflater;

	private LinearLayout headView;
                              //组件;
	private TextView tipsText;
	private TextView lastUpdatedText;
	private ImageView arrowImage;
	private ProgressBar progressBar;
	
	                           //旋转动画;
	private RotateAnimation animation;
	private RotateAnimation reverseAnimation;
	                          //flags
	// 用于保证startY的值在一个完整的touch事件中只被记录一次;
	private boolean isRecored;
	
	private boolean isBack;
	private boolean isRefreshable;
	
	private int headContentWidth;
	private int headContentHeight;

	private int startY;
	private int state;
	private int firstItemIndex;
	

	private OnRefreshListener refreshListener;

	public MyListView(Context context) {
		super(context);
		initUI(context);
	}
	public MyListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initUI(context);
	}
	public MyListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initUI(context);
	}
	
//=====================================================================================================
	public void initUI(Context context){
		
		inflater=LayoutInflater.from(context);
		this.headView=(LinearLayout)inflater.inflate(R.layout.listview_head_layout,null,false);
		this.tipsText=(TextView)headView.findViewById(R.id.listview_head_tips);
		this.lastUpdatedText=(TextView)headView.findViewById(R.id.listview_head_updateTime);
		this.progressBar=(ProgressBar)headView.findViewById(R.id.listview_head_pBar);
		this.arrowImage=(ImageView)headView.findViewById(R.id.listview_head_arrow);
		
		this.measureView(headView);
		headContentHeight = headView.getMeasuredHeight();
		headContentWidth = headView.getMeasuredWidth();

		headView.setPadding(0, -1*headContentHeight, 0, 0);
		headView.invalidate();
		
		super.addHeaderView(headView);
		super.setOnScrollListener(this);
		                                                         //animation;               
		animation = new RotateAnimation(0, -180,           //逆时针旋转;
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		animation.setInterpolator(new LinearInterpolator());
		animation.setDuration(250);
		animation.setFillAfter(true);

		reverseAnimation = new RotateAnimation(-180, 0,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		reverseAnimation.setInterpolator(new LinearInterpolator());
		reverseAnimation.setDuration(200);
		reverseAnimation.setFillAfter(true);
                                                 //State=DONE; 无状态;
		this.state = DONE;
		this.isRefreshable = false;
	}
	
	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
		this.firstItemIndex=firstVisibleItem;
		
	}
	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		
	}
//====================================================================================================
	public boolean onTouchEvent(MotionEvent e){
		if(this.isRefreshable){
			switch(e.getAction()){
			case MotionEvent.ACTION_DOWN:
				if(this.firstItemIndex==0&&!this.isRecored){
					this.isRecored=true;
					this.startY=(int)e.getY();
				}
				break; 
			case MotionEvent.ACTION_UP:
				if(state!=MyListView.LOADING){
					switch(state){
					case MyListView.DONE:
						break;
					case MyListView.PULL_TO_REFRESH:
						state=MyListView.DONE;
						this.changeHeaderViewByState();
						break;
					case MyListView.RELEASE_TO_REFRESH:
						state=MyListView.LOADING;         //异步;
						this.changeHeaderViewByState();
						this.onRefresh();
						break;
					}
				}
				
				this.isBack=false;
				this.isRecored=false;
				
				break;
			case MotionEvent.ACTION_MOVE:
				int tempY=(int)e.getY();
				
				if(this.firstItemIndex==0&&!this.isRecored){
					this.isRecored=true;
					this.startY=tempY;
				}
				//-------------------------------------------------------------------------------
				if(state!=LOADING&&this.isRecored){
					                                    //注意是异步加载;
					
					// 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
					if(state==MyListView.PULL_TO_REFRESH){
						setSelection(0);
						                                // 下拉到可以进入RELEASE_TO_REFRESH的状态
						if((tempY-startY)/RATE > this.headContentHeight){
							state=MyListView.RELEASE_TO_REFRESH;
							isBack=true;
							this.changeHeaderViewByState();
						}else if(tempY-startY<=0){
							state=DONE;                 //恢复DONE状态;
							this.changeHeaderViewByState();
						}
					}
					else if(state==MyListView.RELEASE_TO_REFRESH){
						setSelection(0);
						this.toTop=(tempY-startY)/RATE-this.headContentHeight;
						System.out.println("======"+this.toTop+"========");
						
						if(tempY-startY>0&&(tempY-startY)/RATE < this.headContentHeight){
							state=MyListView.PULL_TO_REFRESH;
							this.changeHeaderViewByState();
						}else if(tempY-startY<=0){
							state=MyListView.DONE;
							this.changeHeaderViewByState();
						}
					}
					else if(state==MyListView.DONE){
						if(tempY-startY>0){
							state=MyListView.PULL_TO_REFRESH;
							this.changeHeaderViewByState();
						}
					}
					
					//========================//更新界面//==============================================
					if(state==MyListView.PULL_TO_REFRESH){
						this.headView.setPadding(0, -1*this.headContentHeight+(tempY-startY)/RATE, 0, 0);
					}
					if(state==MyListView.RELEASE_TO_REFRESH){
						this.headView.setPadding(0, (tempY-startY)/RATE-this.headContentHeight, 0, 0);
					}
				}
				break;
			}
		}
		return super.onTouchEvent(e);
	}
	
	public void changeHeaderViewByState(){
		switch(state){
		case PULL_TO_REFRESH:
			progressBar.setVisibility(View.GONE);
			tipsText.setVisibility(View.VISIBLE);
			lastUpdatedText.setVisibility(View.VISIBLE);
			
			arrowImage.clearAnimation();
			arrowImage.setVisibility(View.VISIBLE);
			// isBack==true表示是由RELEASE_To_REFRESH状态转变来的
			if (isBack) {
				isBack = false;
				arrowImage.startAnimation(reverseAnimation);
				tipsText.setText("下拉刷新");
			} else {
				tipsText.setText("下拉刷新");
			}
			break;
		case RELEASE_TO_REFRESH:
			arrowImage.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.GONE);
			tipsText.setVisibility(View.VISIBLE);
			lastUpdatedText.setVisibility(View.VISIBLE);

			arrowImage.clearAnimation();
			arrowImage.startAnimation(animation);

			tipsText.setText("松开刷新");
			break;
		case LOADING:
			new AsyncMove().execute(this.toTop);
			
			lastUpdatedText.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.VISIBLE);
			arrowImage.setVisibility(View.GONE);
			arrowImage.clearAnimation();
			
			tipsText.setText("正在加载...");

			break;
		case DONE:
			headView.setPadding(0, -1 * headContentHeight, 0, 0);

			progressBar.setVisibility(View.GONE);
			lastUpdatedText.setVisibility(View.VISIBLE);
			
			arrowImage.clearAnimation();
			arrowImage.setImageResource(R.drawable.arrow);
			tipsText.setText("下拉刷新");

			break;	
		}
	}
//====================================================================================================
	public interface OnRefreshListener{
		public  void onRefresh();
	}
	public void setOnRefreshListener(OnRefreshListener onRefreshListener){
		this.isRefreshable=true;
		this.refreshListener=onRefreshListener;
		
	}
	public void onRefreshComplete() {
		state=DONE;
		lastUpdatedText.setText("最近更新:"+new SimpleDateFormat("MM-dd HH:mm").format(new Date(System.currentTimeMillis())));
		changeHeaderViewByState();
	}

	public void onRefresh() {
		if (refreshListener!=null) {
			refreshListener.onRefresh();
		}
	}

	public void setAdapter(BaseAdapter adapter) {
		lastUpdatedText.setText("最近更新:" +new SimpleDateFormat("MM-dd HH:mm").format(new Date(System.currentTimeMillis())));
		super.setAdapter(adapter);
	}
//==================此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headView的width以及height===============
	@SuppressWarnings("deprecation")
	public void measureView(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
		}
		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
					MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0,
					MeasureSpec.UNSPECIFIED);
		}
		child.measure(childWidthSpec, childHeightSpec);
	}
//====================================================================================================\
	private class AsyncMove extends AsyncTask<Integer,Integer,Void>{

		@Override
		protected Void doInBackground(Integer... top) {
			top[0]=top[0]-50;
			
			while(top[0]>=0){
				publishProgress(top[0]);
				top[0]=top[0]-50;
				try{
					Thread.sleep(10);
				}catch(Exception e){}
			}
			
			return null;
		}
		protected void onProgressUpdate(Integer...value){
			MyListView.this.headView.setPadding(0, value[0], 0, 0);
		}
		protected void onPostExecute(Void v){
			MyListView.this.headView.setPadding(0, 0, 0, 0);
		}
		
	}
//====================================================================================================
}

Sumsang S4实测截图如下:

【上篇】
【下篇】

抱歉!评论已关闭.