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

来源:互联网 发布:苹果电脑的ppt软件 编辑:程序博客网 时间:2024/06/05 15:12

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


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);}@Overridepublic 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;@Overridepublic void onScrollStateChanged(AbsListView arg0, int arg1) {}@Overridepublic 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的sizeif (state == PULL_To_REFRESH) {footView.setPadding(0, -1 * m_headContentHeight + (startY - tempY) / RATIO, 0, 0);}// 更新headView的paddingTopif (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的sizeif (state == PULL_To_REFRESH) {headView.setPadding(0, -1 * headContentHeight + (tempY - startY) / RATIO, 0, 0);}// 更新headView的paddingTopif (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以及heightprivate 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);}}