自定义listview,添加headerview和footerview,监听滚动事件;
MyListView.java:
import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.AbsListView; import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class MyListView extends ListView implements AbsListView.OnScrollListener { public int height; private int offsetheight;//记录listview下拉偏移量 private ImageView arrow; private TextView dateText; private TextView tipsText; private View headerView;//listview头布局 public View footView;//listview脚布局 private int totalItemCount;//全部的列表项 private int startY;//listview开始下拉的位置 private int firstVisibleItem;//记录第一个下拉的项 private int lastVisibleItem; private int STATE;//记录当前状态 private boolean isFromBegin;//记录是否从头开始下拉 private final int NONE = 0;//listview处于静态 private final int PULL = 1;//listview处于下拉状态 private final int RELESE = 2;//listview处于松开刷新的状态 private final int RELESING = 3;//listview处于正在刷新状态 private LoadListener loadListener;//底部加载监听 public ProgressBar progressBar; private RefreshListener refreshListener;//头部刷新监听 public void setRefreshListener(RefreshListener refreshListener) { this.refreshListener = refreshListener; } public void setLoadListener(LoadListener loadListener) { this.loadListener = loadListener; } public MyListView(Context context) { super(context); init(context); } public MyListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public MyListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } /** * 初始化组件,添加headerView和footView */ public void init(Context context) { headerView = LayoutInflater.from(context).inflate(R.layout.headerview, null); footView = LayoutInflater.from(context).inflate(R.layout.footview, null); arrow = (ImageView) headerView.findViewById(R.id.arrow); dateText = (TextView) headerView.findViewById(R.id.date); tipsText = (TextView) headerView.findViewById(R.id.tips); progressBar = (ProgressBar) headerView.findViewById(R.id.progressbar); notifyView(headerView); height = headerView.getMeasuredHeight(); setPadding(-height); footView.setVisibility(INVISIBLE); this.addHeaderView(headerView);//添加头布局 this.addFooterView(footView);//添加脚布局 this.setOnScrollListener(this); this.setVerticalScrollBarEnabled(false);//隐藏滚动条 } /** * 通知父布局测量子布局的尺寸 */ public void notifyView(View view) { ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); if (layoutParams == null) { layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int with = ViewGroup.getChildMeasureSpec(0, 0, view.getWidth()); int height; int viewheight = view.getHeight(); if (viewheight > 0) { MeasureSpec.makeMeasureSpec(viewheight, MeasureSpec.EXACTLY); } else { MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } view.measure(with, viewheight); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { //判断是否到达列表的最底部和加载数据 if (this.lastVisibleItem == this.totalItemCount) { footView.setVisibility(VISIBLE); loadListener.getLoadData(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { this.firstVisibleItem = firstVisibleItem; this.lastVisibleItem = firstVisibleItem + visibleItemCount; this.totalItemCount = totalItemCount; } /** * 监听listview的touch事件 */ @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: if (firstVisibleItem == 0) { STATE = NONE; isFromBegin = true; startY = (int) ev.getY(); } break; case MotionEvent.ACTION_MOVE: move(ev); break; case MotionEvent.ACTION_UP: if (STATE == RELESE) { STATE = RELESING; ChangeViewFromState(STATE); } else if (STATE == PULL) { STATE = NONE; ChangeViewFromState(STATE); } break; default: break; } return super.onTouchEvent(ev); } /** * @param ev * listview滑动状态的处理,分发处理listview下拉达到的状态 */ public void move(MotionEvent ev) { if (!isFromBegin) { return; } offsetheight = (int) ev.getY() - startY; switch (STATE) { case NONE: setPadding(offsetheight); if (offsetheight > 0) { STATE = PULL; ChangeViewFromState(STATE); } break; case PULL: setPadding(offsetheight); if (offsetheight >= height + 60) { STATE = RELESE; ChangeViewFromState(STATE); } break; case RELESE: setPadding(offsetheight); if (offsetheight < height + 60) { STATE = PULL; ChangeViewFromState(STATE); } break; } } /** * 设置headerview的padding * @param offsetHeight */ public void setPadding(int offsetHeight) { headerView.setPadding(headerView.getPaddingLeft(), -height + offsetHeight, headerView.getPaddingLeft(), headerView.getPaddingBottom()); headerView.invalidate(); } /** * 根据当前的状态改变headerview的view * @param state */ public void ChangeViewFromState(int state) { RotateAnimation animation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); animation.setDuration(500); animation.setFillAfter(true); RotateAnimation animation1 = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); animation1.setDuration(500); animation1.setFillAfter(true); switch (state) { case NONE: arrow.clearAnimation(); setPadding(-height); tipsText.setText("下拉刷新"); break; case PULL: arrow.clearAnimation(); //arrow.setAnimation(animation1); tipsText.setText("下拉刷新"); arrow.setVisibility(VISIBLE); progressBar.setVisibility(GONE); break; case RELESE: arrow.clearAnimation(); arrow.setAnimation(animation); tipsText.setText("松开刷新"); break; case RELESING: setPadding(height); arrow.clearAnimation(); tipsText.setText("正在刷新..."); arrow.setVisibility(GONE); progressBar.setVisibility(VISIBLE); refreshListener.getRefreshData(); break; } } /** * listview的下拉刷新数据接口 */ public interface RefreshListener { public void getRefreshData(); } /** * listview的上拉加载数据接口 */ public interface LoadListener { public void getLoadData(); } /** * 更新headerview刷新的时间 */ public void refreshTime() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm", Locale.CHINA); Date date = new Date(System.currentTimeMillis()); String datatime = simpleDateFormat.format(date); dateText.setText(datatime); } }
其它部分比较简单,就不展示出来了