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

listview工具类:上拉刷新+下拉刷新

2013年10月05日 ⁄ 综合 ⁄ 共 14725字 ⁄ 字号 评论关闭

用网上的下拉刷新+上拉更多改的,欢迎大家反馈问题,并一同完善,以后用的时候就方便了

package com.tts.dyq.util;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.IInterface;
import android.provider.ContactsContract.CommonDataKinds.Event;
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.WindowManager;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.tts.dyq.R;

@SuppressLint("SimpleDateFormat")
public class PullToRefreshListView_Both extends ListView implements OnScrollListener {

	private static final String TAG = "listview";
	private final static int RELEASE_To_REFRESH = 0; // 释放
	private final static int PULL_To_REFRESH = 1;// 下拉刷新
	private final static int REFRESHING = 2; // 正在刷新
	private final static int DONE = 3; // 按下
	private final static int LOADING = 4;
	// 实际的padding的距离与界面上偏移距离的比例
	private final static int RATIO = 3;
	private LayoutInflater inflater;
	private LinearLayout headView;
	private TextView tipsTextview;
	private TextView lastUpdatedTextView;
	private ImageView arrowImageView;
	private ProgressBar progressBar;
	private RotateAnimation animation;
	private RotateAnimation reverseAnimation;
	// 用于保证startY的值在一个完整的touch事件中只被记录一次
	private boolean isRecored = false;
	private int headContentWidth;
	private int headContentHeight;
	private int firstItemIndex;
	private int state;
	private boolean isBack;
	private OnRefreshListener refreshListener;
	private boolean isRefreshable;

	private LinearLayout footView;
	private TextView m_tipsTextview;
	private TextView m_lastUpdatedTextView;
	private ImageView m_arrowImageView;
	private ProgressBar m_progressBar;
	private boolean m_isRecored = false;
	private int m_headContentWidth;
	private int m_headContentHeight;
	private int startY;
	private int m_firstItemIndex;
	private boolean m_isBack;
	private OnRefreshListener m_refreshListener;
	private boolean mRefreshHead;

	private int mTotalSize;

	public PullToRefreshListView_Both(Context context) {
		super(context);
		init(context);

	}

	private void init(Context context) {
		inflater = LayoutInflater.from(context);
		initHeadView(context);
		initFootView(context);
		initAnimation();
		state = DONE;
		isRefreshable = false;
		setOnScrollListener(this);
	}

	/**
	 * 初始化动画
	 */
	private void initAnimation() {
		animation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		animation.setInterpolator(new LinearInterpolator());
		animation.setDuration(250);
		animation.setFillAfter(true);
		reverseAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
				0.5f);
		reverseAnimation.setInterpolator(new LinearInterpolator());
		reverseAnimation.setDuration(200);
		reverseAnimation.setFillAfter(true);
	}

	public PullToRefreshListView_Both(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	private void initHeadView(Context context) {
		headView = (LinearLayout) inflater.inflate(R.layout.head, null);
		arrowImageView = (ImageView) headView.findViewById(R.id.head_arrowImageView);
		progressBar = (ProgressBar) headView.findViewById(R.id.head_progressBar);
		tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);
		lastUpdatedTextView = (TextView) headView.findViewById(R.id.head_lastUpdatedTextView);
		measureView(headView);
		headContentHeight = headView.getMeasuredHeight();
		headContentWidth = headView.getMeasuredWidth();
		headView.setPadding(0, -1 * headContentHeight, 0, 0);
		headView.invalidate();
		Log.v("size", "width:" + headContentWidth + " height:" + headContentHeight);
		addHeaderView(headView, null, false);

	}

	private void initFootView(Context context) {
		footView = (LinearLayout) inflater.inflate(R.layout.foot, null);
		m_arrowImageView = (ImageView) footView.findViewById(R.id.foot_arrowImageView);
		m_progressBar = (ProgressBar) footView.findViewById(R.id.foot_progressBar);
		m_tipsTextview = (TextView) footView.findViewById(R.id.foot_tipsTextView);
		m_lastUpdatedTextView = (TextView) footView.findViewById(R.id.foot_lastUpdatedTextView);
		measureView(footView);
		m_headContentHeight = footView.getMeasuredHeight();
		m_headContentWidth = footView.getMeasuredWidth();
		footView.setPadding(0, -1 * m_headContentHeight, 0, 0);
		footView.invalidate();
		Log.v("size", "width:" + m_headContentWidth + " height:" + m_headContentHeight);
		addFooterView(footView, null, false);
	}

	@Override
	public void onScroll(AbsListView arg0, int firstVisiableItem, int visibleItemCount, int totalItemCount) {
		firstItemIndex = firstVisiableItem;
		mTotalSize = totalItemCount;
		m_firstItemIndex = totalItemCount;

		mIsLast = (firstVisiableItem + visibleItemCount) == totalItemCount ? true : false;
//		Log.e(TAG, "-------onScroll-------mIsLastItemVisible=" + mIsLast);
	}

	private boolean mIsLast = false;

	@Override
	public void onScrollStateChanged(AbsListView arg0, int arg1) {
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// Log.e(TAG, "isRefreshable=" + isRefreshable);
		if (getAdapter() == null)
			return false;

		if (isRefreshable) {
			switch (event.getAction()) {
			// 在down时候记录当前Y的位置
			case MotionEvent.ACTION_DOWN:
				startY = (int) event.getY();
				// Log.e(TAG, "------x-----startY=" + startY);
				break;
			case MotionEvent.ACTION_UP:
//				Log.e(TAG, "-------------------ACTION_UP-------------------");
				if (mRefreshHead) {
					updateHeadOnUp();
				} else {
					updateFootViewOnUp(event);
				}

			case MotionEvent.ACTION_MOVE:
				int tempY = (int) event.getY();
				// Log.e(TAG, "------ACTION_MOVE-----tempY=" + tempY +
				// " ;startY=" + startY);
				if (tempY > startY) {
					mRefreshHead = true;
					if (firstItemIndex == 0) {
						updateHeadViewOnMove(tempY);
					}

				} else {
					mRefreshHead = false;
					if (mIsLast) {
						updateFootViewOnMove(tempY);
					}
				}

				break;
			}
		}
		return super.onTouchEvent(event);
	}

	private void updateFootViewOnUp(MotionEvent event) {
		Log.e(TAG, "---------foot----up------------status-----------" + state);

		if (state != REFRESHING && state != LOADING) {
			if (state == DONE) {
				// 什么都不做
//				Log.e(TAG, "--------foot---up-----0------");
				footView.setPadding(0, -1 * m_headContentHeight, 0, 0);
				headView.setPadding(0, -1 * headContentHeight, 0, 0);
			}
			// 由下拉刷新状态,到done状态
			if (state == PULL_To_REFRESH) {
//				Log.e(TAG, "--------foot---up-----1------");
				state = DONE;
				changeHeaderViewByState();
				Log.v(TAG, "由上拉刷新状态,到done状态");
			}

			if (state == RELEASE_To_REFRESH) {
//				Log.e(TAG, "--------foot---up-----2------");
				state = REFRESHING;
				changeHeaderViewByState();
				onRefresh();
				Log.v(TAG, "由松开刷新状态,到done状态");
			}
		}
		m_isRecored = false;
		m_isBack = false;
	}

	private void updateHeadOnUp() {
//		Log.e(TAG, "---------head----up-------------------status-----------" + state);
		if (state != REFRESHING && state != LOADING) {
			if (state == DONE) {
//				Log.e(TAG, "----head----up----------0-----");
				// 什么都不做
				footView.setPadding(0, -1 * m_headContentHeight, 0, 0);
				headView.setPadding(0, -1 * headContentHeight, 0, 0);
			}
			// 由下拉刷新状态,到done状态
			if (state == PULL_To_REFRESH) {
//				Log.e(TAG, "----head----up---------1------");
				state = DONE;
				changeHeaderViewByState();
				Log.v(TAG, "由下拉刷新状态,到done状态");
			}

			if (state == RELEASE_To_REFRESH) {
//				Log.e(TAG, "----head----up--------2-------");
				state = REFRESHING;
				changeHeaderViewByState();
				onRefresh();
				Log.v(TAG, "由松开刷新状态,到done状态");
			}
		}
		isRecored = false;
		isBack = false;
	}

	private void changeHeaderViewByState() {
		// Log.e(TAG, "---------changeHeaderViewByState------in----");
		switch (state) {
		// 松开刷新状态
		case RELEASE_To_REFRESH:
			if (mRefreshHead) {
				arrowImageView.setVisibility(View.VISIBLE);
				progressBar.setVisibility(View.GONE);
				tipsTextview.setVisibility(View.VISIBLE);
				lastUpdatedTextView.setVisibility(View.VISIBLE);
				arrowImageView.clearAnimation();
				arrowImageView.startAnimation(animation);
				tipsTextview.setText("松开刷新");
				Log.v(TAG, "当前状态,松开刷新");
			} else {
				// Log.e(TAG, "---------changeHeaderViewByState-----1-----");
				m_arrowImageView.setVisibility(View.VISIBLE);
				m_progressBar.setVisibility(View.GONE);
				m_tipsTextview.setVisibility(View.VISIBLE);
				m_lastUpdatedTextView.setVisibility(View.VISIBLE);
				m_arrowImageView.clearAnimation();
				m_arrowImageView.startAnimation(animation);
				m_tipsTextview.setText("松开刷新");
				Log.v(TAG, "当前状态,松开刷新");
			}

			break;
		// 下拉刷新
		case PULL_To_REFRESH:
			if (mRefreshHead) {
				progressBar.setVisibility(View.GONE);
				tipsTextview.setVisibility(View.VISIBLE);
				lastUpdatedTextView.setVisibility(View.VISIBLE);
				arrowImageView.clearAnimation();
				arrowImageView.setVisibility(View.VISIBLE);
				// 是由RELEASE_To_REFRESH状态转变来的
				// 箭头反转向上
				if (isBack) {
					isBack = false;
					arrowImageView.clearAnimation();
					arrowImageView.startAnimation(reverseAnimation);
					tipsTextview.setText("下拉刷新");
				} else {
					tipsTextview.setText("下拉刷新");
				}

				footView.setPadding(0, -1 * m_headContentHeight, 0, 0);
			} else {
				// Log.e(TAG, "---------changeHeaderViewByState---2-------");
				m_progressBar.setVisibility(View.GONE);
				m_tipsTextview.setVisibility(View.VISIBLE);
				m_lastUpdatedTextView.setVisibility(View.VISIBLE);
				m_arrowImageView.clearAnimation();
				m_arrowImageView.setVisibility(View.VISIBLE);
				// 是由RELEASE_To_REFRESH状态转变来的
				// 箭头反转向上
				if (m_isBack) {
					m_isBack = false;
					m_arrowImageView.clearAnimation();
					m_arrowImageView.startAnimation(reverseAnimation);
					m_tipsTextview.setText("上拉刷新");
				} else {
					m_tipsTextview.setText("上拉刷新");
				}
				headView.setPadding(0, -1 * headContentHeight, 0, 0);
			}

			Log.v(TAG, "当前状态,下拉刷新");
			break;
		// 刷新中 状态
		case REFRESHING:
			if (mRefreshHead) {

				headView.setPadding(0, 0, 0, 0);
				progressBar.setVisibility(View.VISIBLE);
				arrowImageView.clearAnimation();
				arrowImageView.setVisibility(View.GONE);
				tipsTextview.setText("正在刷新...");
				lastUpdatedTextView.setVisibility(View.VISIBLE);
			} else {
				// Log.e(TAG, "---------changeHeaderViewByState---3-------");
				footView.setPadding(0, 0, 0, 0);
				m_progressBar.setVisibility(View.VISIBLE);
				m_arrowImageView.clearAnimation();
				m_arrowImageView.setVisibility(View.GONE);
				m_tipsTextview.setText("正在刷新...");
				m_lastUpdatedTextView.setVisibility(View.VISIBLE);
			}
			Log.v(TAG, "当前状态,正在刷新...");
			break;
		// 刷新完毕
		case DONE:
			if (mRefreshHead) {
				firstItemIndex = 0;
				headView.setPadding(0, -1 * headContentHeight, 0, 0);
				progressBar.setVisibility(View.GONE);
				arrowImageView.clearAnimation();
				arrowImageView.setImageResource(R.drawable.goicon);
				tipsTextview.setText("下拉刷新");
				lastUpdatedTextView.setVisibility(View.VISIBLE);
			} else {
				// Log.e(TAG, "---------changeHeaderViewByState---4-------");
				m_firstItemIndex = mTotalSize;
				footView.setPadding(0, -1 * m_headContentHeight, 0, 0);
				m_progressBar.setVisibility(View.GONE);
				m_arrowImageView.clearAnimation();
				m_arrowImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow_up);
				m_tipsTextview.setText("上拉刷新");
				m_lastUpdatedTextView.setVisibility(View.VISIBLE);

			}
			Log.v(TAG, "当前状态,done");
			break;
		}
	}

	public void setOnRefreshListener(OnRefreshListener headViewRefreshListener,
			OnRefreshListener footViewRefreshListener) {
		this.refreshListener = headViewRefreshListener;
		this.m_refreshListener = footViewRefreshListener;
		isRefreshable = true;
	}

	public void updateFootViewOnMove(int tempY) {
		Log.e(TAG, "---------------------updateFootViewOnMove------------------------------");

		if (!m_isRecored && m_firstItemIndex == mTotalSize) {
			Log.v(TAG, "在move时候记录下位置");
			m_isRecored = true;
			startY = tempY;
		}
		if (state != REFRESHING && m_isRecored && state != LOADING) {
			// 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
			// 可以松手去刷新了
			if (state == RELEASE_To_REFRESH) {
				setSelection(mTotalSize);
				// 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
				if (((startY - tempY) / RATIO < m_headContentHeight) && (startY - tempY) > 0) {
					state = PULL_To_REFRESH;
					changeHeaderViewByState();
					Log.e(TAG, "由松开刷新状态转变到上拉刷新状态");
				}
				// 一下子推到顶了
				else if (startY - tempY <= 0) {
					state = DONE;
					changeHeaderViewByState();
					Log.e(TAG, "由松开刷新状态转变到done状态");
				}
				// 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
				else {
					// 不用进行特别的操作,只用更新paddingTop的值就行了
				}
			}
			// 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
			if (state == PULL_To_REFRESH) {
				setSelection(mTotalSize);
				// 下拉到可以进入RELEASE_TO_REFRESH的状态
				if ((startY - tempY) / RATIO >= m_headContentHeight) {
					state = RELEASE_To_REFRESH;
					m_isBack = true;
					changeHeaderViewByState();
					Log.e(TAG, "由done或者上拉刷新状态转变到松开刷新");
				}
				// 上推到顶了
				else if (startY - tempY <= 0) {
					state = DONE;
					changeHeaderViewByState();
					Log.e(TAG, "由DOne或者上拉刷新状态转变到done状态");
				}
			}
			// done状态下
			if (state == DONE) {
				if (startY - tempY > 0) {
					state = PULL_To_REFRESH;
					changeHeaderViewByState();
				}
			}
			// 更新headView的size
			if (state == PULL_To_REFRESH) {
				footView.setPadding(0, -1 * m_headContentHeight + (startY - tempY) / RATIO, 0, 0);
			}
			// 更新headView的paddingTop
			if (state == RELEASE_To_REFRESH) {
				footView.setPadding(0, 10, 0, 0);
			}
		}
		headView.setPadding(0, -1 * headContentHeight , 0, 0);
	}

	public void updateHeadViewOnMove(int tempY) {
		Log.e(TAG, "-------Head----OnMove-----------");

		if (!isRecored && firstItemIndex == 0) {
			Log.v(TAG, "在move时候记录下位置");
			isRecored = true;
			startY = tempY;
		}
		if (state != REFRESHING && isRecored && state != LOADING) {
			// 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
			// 可以松手去刷新了
			if (state == RELEASE_To_REFRESH) {
				setSelection(0);
				// 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
				if (((tempY - startY) / RATIO < headContentHeight) && (tempY - startY) > 0) {
					state = PULL_To_REFRESH;
					changeHeaderViewByState();
					Log.v(TAG, "由松开刷新状态转变到下拉刷新状态");
				}
				// 一下子推到顶了
				else if (tempY - startY <= 0) {
					state = DONE;
					changeHeaderViewByState();
					Log.v(TAG, "由松开刷新状态转变到done状态");
				}
				// 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
				else {
					// 不用进行特别的操作,只用更新paddingTop的值就行了
				}
			}
			// 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
			if (state == PULL_To_REFRESH) {
				setSelection(0);
				// 下拉到可以进入RELEASE_TO_REFRESH的状态
				if ((tempY - startY) / RATIO >= headContentHeight) {
					state = RELEASE_To_REFRESH;
					isBack = true;
					changeHeaderViewByState();
					Log.v(TAG, "由done或者下拉刷新状态转变到松开刷新");
				}
				// 上推到顶了
				else if (tempY - startY <= 0) {
					state = DONE;
					changeHeaderViewByState();
					Log.v(TAG, "由DOne或者下拉刷新状态转变到done状态");
				}
			}
			// done状态下
			if (state == DONE) {
				if (tempY - startY > 0) {
					state = PULL_To_REFRESH;
					changeHeaderViewByState();
				}
			}
			// 更新headView的size
			if (state == PULL_To_REFRESH) {
				headView.setPadding(0, -1 * headContentHeight + (tempY - startY) / RATIO, 0, 0);
			}
			// 更新headView的paddingTop
			if (state == RELEASE_To_REFRESH) {
				headView.setPadding(0, 10, 0, 0);
			}
		}
		footView.setPadding(0, -1 * m_headContentHeight, 0, 0);
	}

	public interface OnRefreshListener {
		public void onRefresh();
	}

	public void onRefreshComplete() {
		if (mRefreshHead) {
			state = DONE;
			SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日  HH:mm");
			String date = format.format(new Date());
			lastUpdatedTextView.setText("最近更新:" + date);
		} else {
			state = DONE;
			SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日  HH:mm");
			String date = format.format(new Date());
			m_lastUpdatedTextView.setText("最近更新:" + date);
		}
		changeHeaderViewByState();
	}

	private void onRefresh() {
		if (mRefreshHead) {
			if (refreshListener != null) {
				refreshListener.onRefresh();
			}
		} else {
			if (m_refreshListener != null) {
				m_refreshListener.onRefresh();
			}
		}
	}

	// 此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headView的width以及height
	private void measureView(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 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);
	}

	public void setAdapter(BaseAdapter adapter) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日  HH:mm");
		String date = format.format(new Date());
		if (mRefreshHead) {
			lastUpdatedTextView.setText("最近更新:" + date);
		} else {
			m_lastUpdatedTextView.setText("最近更新:" + date);
		}

		super.setAdapter(adapter);
	}
}

抱歉!评论已关闭.