- public class MyListView extends ListView implements OnScrollListener {
- public final int RATIO = 5;// 手拖动时,手指拖动距离与header下移的倍数
- private final int LOADING = 0;// 正在加载
- private final int RELEASE_To_REFRESH = 2;// 正在下拉状态,即将松手进行刷新
- private final int DONE = 3;// 完成
- private final int HIDE_To_REFRESH = 1;// 未下拉或已完成状态,设置padding为负值把header挡住
- private int refreshStatus;// 下拉刷新过程状态变量
- private LinearLayout hearderLayout;
- private ImageView arrowImageView;
- private ProgressBar progressBar;
- private TextView tipsTextview;
- private TextView lastUpdatedTime;
- private int headContentHeight;
- private int headContentWidth;
- private RotateAnimation animation;
- private RotateAnimation reverseAnimation;
- private boolean isStartRefreshEvent = false;// 下拉刷新事件是否已经开始
- private boolean isRefreshable = false;// 是否设置下拉刷新监听
- private int firstItemIndex;
- private OnRefreshListener refreshListener;
- public MyListView (Context context) {
- super(context);
- init(context);
- }
- public MyListView (Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context);
- }
- private void init(Context context) {
- LayoutInflater inflater = LayoutInflater.from(context);
- hearderLayout = (LinearLayout) inflater.inflate(R.layout.list_view_header, null);
- // 下拉箭头
- arrowImageView = (ImageView) hearderLayout.findViewById(R.id.head_arrowImageView);
- // 进度条
- progressBar = (ProgressBar) hearderLayout.findViewById(R.id.head_progressBar);
- // 下拉提示 刷新
- tipsTextview = (TextView) hearderLayout.findViewById(R.id.head_tipsTextView);
- // 最新一次刷新时间
- lastUpdatedTime = (TextView) hearderLayout.findViewById(R.id.head_lastUpdatedTextView);
- // 计算head的高宽
- this.measureView(hearderLayout);
- headContentHeight = hearderLayout.getMeasuredHeight();
- headContentWidth = hearderLayout.getMeasuredWidth();
- // 初始状态是 隐藏掉head 布局
- hearderLayout.setPadding(0, -1 * headContentHeight, 0, 0);
- hearderLayout.invalidate();
- Log.e("sys", "width:" + headContentWidth + " height:" + headContentHeight);
- // list添加头文件
- addHeaderView(hearderLayout, null, false);
- setOnScrollListener(this);// TODO
- // 下拉以及恢复动画
- 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);
- refreshStatus = DONE;
- }
- @Override
- public void onScroll(AbsListView arg0, int firstVisiableItem, int arg2, int arg3) {
- firstItemIndex = firstVisiableItem;
- }
- @Override
- public void onScrollStateChanged(AbsListView arg0, int arg1) {
- }
- private int startY = 0;
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (firstItemIndex == 0 && isRefreshable) {
- switch (event.getAction()) {
- // 在down时候记录当前Y的位置
- case MotionEvent.ACTION_DOWN:
- if (!isStartRefreshEvent) {
- isStartRefreshEvent = true;
- startY = (int) event.getY();
- }
- break;
- case MotionEvent.ACTION_MOVE:
- int tempY = (int) event.getY();
- int scrollY = (tempY - startY) / RATIO;
- Log.i("sys", "拉开方向 " + scrollY);
- if (!isStartRefreshEvent) {
- isStartRefreshEvent = true;
- startY = tempY;
- } else if (isStartRefreshEvent && refreshStatus != LOADING) {
- // 可以松手去刷新了
- if (refreshStatus == RELEASE_To_REFRESH) {
- setSelection(0);
- // header被用户拉下来后,又往上推了,推到了已经小于header高度时,则推回去,并取消刷新
- if (scrollY < headContentHeight && scrollY > 0) {
- refreshStatus = HIDE_To_REFRESH;
- this.changeHeaderView();
- }
- // 一下子推到顶了
- else if (scrollY <= 0) {
- refreshStatus = DONE;
- this.changeHeaderView();
- }
- }
- // 还没有到达显示松开刷新的时候,DONE或者是HIDE_To_REFRESH状态
- if (refreshStatus == HIDE_To_REFRESH) {
- setSelection(0);
- // 下拉至超过header本身高度后,可以进入RELEASE_TO_REFRESH的状态
- if (scrollY > headContentHeight) {
- refreshStatus = RELEASE_To_REFRESH;
- this.changeHeaderView();
- }
- // 上推到顶了
- else if (scrollY <= 0) {
- refreshStatus = DONE;
- this.changeHeaderView();
- }
- }
- // done状态下
- if (refreshStatus == DONE) {
- if (scrollY > 0) {
- refreshStatus = HIDE_To_REFRESH;
- this.changeHeaderView();
- }
- }
- // 更新headView的size
- if (refreshStatus == HIDE_To_REFRESH) {
- hearderLayout.setPadding(0, -1 * headContentHeight + scrollY, 0, 0);
- }
- // 更新headView的paddingTop
- if (refreshStatus == RELEASE_To_REFRESH) {
- hearderLayout.setPadding(0, scrollY - headContentHeight, 0, 0);
- }
- }
- break;
- case MotionEvent.ACTION_UP:
- if (refreshStatus != LOADING) {
- if (refreshStatus == DONE) {
- // 什么都不做
- }
- // 由下拉刷新状态,到done状态
- if (refreshStatus == HIDE_To_REFRESH) {
- refreshStatus = DONE;
- this.changeHeaderView();
- }
- if (refreshStatus == RELEASE_To_REFRESH) {
- refreshStatus = LOADING;
- this.changeHeaderView();
- onRefresh();
- }
- }
- isStartRefreshEvent = false;
- break;
- }
- }
- return super.onTouchEvent(event);
- }
- private void changeHeaderView() {
- switch (refreshStatus) {
- // 松开刷新状态
- case RELEASE_To_REFRESH:
- arrowImageView.setVisibility(View.VISIBLE);
- progressBar.setVisibility(View.GONE);
- tipsTextview.setVisibility(View.VISIBLE);
- lastUpdatedTime.setVisibility(View.VISIBLE);
- arrowImageView.clearAnimation();
- arrowImageView.startAnimation(animation);
- tipsTextview.setText("松开刷新");
- break;
- // 下拉刷新
- case HIDE_To_REFRESH:
- progressBar.setVisibility(View.GONE);
- tipsTextview.setVisibility(View.VISIBLE);
- lastUpdatedTime.setVisibility(View.VISIBLE);
- arrowImageView.setVisibility(View.VISIBLE);
- // 是由RELEASE_To_REFRESH状态转变来的
- arrowImageView.clearAnimation();
- arrowImageView.startAnimation(reverseAnimation);
- tipsTextview.setText("下拉刷新");
- break;
- // 刷新中 状态
- case LOADING:
- hearderLayout.setPadding(0, 0, 0, 0);
- progressBar.setVisibility(View.VISIBLE);
- arrowImageView.clearAnimation();
- arrowImageView.setVisibility(View.GONE);
- tipsTextview.setText("正在刷新...");
- lastUpdatedTime.setVisibility(View.VISIBLE);
- break;
- // 刷新完毕
- case DONE:
- hearderLayout.setPadding(0, -1 * headContentHeight, 0, 0);
- progressBar.setVisibility(View.GONE);
- arrowImageView.clearAnimation();
- // arrowImageView.setImageResource(R.drawable.goicon);
- tipsTextview.setText("下拉刷新");
- lastUpdatedTime.setVisibility(View.VISIBLE);
- break;
- }
- }
- public void setonRefreshListener(OnRefreshListener refreshListener) {
- this.refreshListener = refreshListener;
- isRefreshable = true;
- }
- public interface OnRefreshListener {
- public void onRefresh();
- }
- public void onRefreshFinished() {
- refreshStatus = DONE;
- DateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
- String date = format.format(new Date());
- lastUpdatedTime.setText("最近更新:" + date);
- changeHeaderView();
- }
- private void onRefresh() {
- if (refreshListener != null) {
- refreshListener.onRefresh();
- }
- }
- // 此方法计算高度
- private 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);
- }
- public void setAdapter(BaseAdapter adapter) {
- DateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
- String date = format.format(new Date());
- lastUpdatedTime.setText("最近更新:" + date);
- super.setAdapter(adapter);
- }
- }
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:background="#ffffff" >
- <!-- 内容 -->
- <RelativeLayout
- android:id="@+id/head_contentLayout"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="30dip" >
- <!-- 箭头图像、进度条 -->
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true" >
- <!-- 箭头 -->
- <ImageView
- android:id="@+id/head_arrowImageView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/arrow"
- android:layout_gravity="center" />
- <!-- 进度条,style集合了一个anim -->
- <ProgressBar
- android:id="@+id/head_progressBar"
- style="@style/wait_anim"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:visibility="gone" />
- </FrameLayout>
- <!-- 提示、最近更新 -->
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:gravity="center_horizontal"
- android:orientation="vertical" >
- <!-- 提示 -->
- <TextView
- android:id="@+id/head_tipsTextView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="下拉刷新"
- android:textSize="15dp" />
- <!-- 最近更新 -->
- <TextView
- android:id="@+id/head_lastUpdatedTextView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="上次更新"
- android:textSize="12dp" />
- </LinearLayout>
- </RelativeLayout>
- </LinearLayout>
- Activity中关键代码:
- mListView.setonRefreshListener(new OnRefreshListener() {
- public void onRefresh() {
- new AsyncTask<Void, Void, Void>() {
- protected Void doInBackground(Void... params) {
- try {
- Thread.sleep(3000);
- } catch (Exception e) {
- e.printStackTrace();
- }
- // dates.addFirst(new AttachmentModule(new Date(), WorkLogContentType.WORKLOG_ATTACHMENT, AttachmentType.Attachment_Nomal));
- return null;
- }
- @Override
- protected void onPostExecute(Void result) {
- adapter.notifyDataSetChanged();
- mListView.onRefreshFinished();
- }
- }.execute(null);
- }
- });
来源: http://www.phpxs.com/code/1002153/