清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>
自定义ListView:
layout:
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); } }
layout:
<?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); } });