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;}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {this.firstItemIndex=firstVisibleItem;}@Overridepublic 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>{@Overrideprotected 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实测截图如下:


更多相关文章

  1. android 网络状态判断
  2. Android隐藏状态栏、导航栏
  3. 使用android自带的SwipeRefreshLayout实现下拉刷新
  4. Android(安卓)- 网络相关
  5. android 黑屏状态下,开屏代码
  6. android保存第一次安装状态并初始化数据
  7. android的Drawable
  8. Android(安卓)4.4 上实现透明导航栏和状态栏 Translucent system
  9. Android之Spinner用法

随机推荐

  1. Android监听器实现(一)Broadcast方式监听
  2. Android(安卓)9 (P) Zygote进程启动源码
  3. Android(安卓)应用热修复与插件化简介
  4. Android中十六进制颜色的基本使用
  5. Android开发中如何做单元测试
  6. Android——实现全国省市区地区选择
  7. Android(安卓)Studio环境下开发百度语音R
  8. 没有经验三天开发一个Android(安卓)app(第
  9. 不用写代码的Android(安卓)2D RPG游戏引
  10. Android内存(内存溢出 内存不足 内存低 .