第一次写博客,有点小激动,以后会坚持下来,记录学习的生涯
经常会用到listview的下拉刷新和上拉加载,虽然个github上有很多开源的框架,总感觉用着不是很理解,决定自己写一写。
效果图:
经常会用到listview的下拉刷新和上拉加载,虽然个github上有很多开源的框架,总感觉用着不是很理解,决定自己写一写。
效果图:
自定义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);
}
}
其它部分比较简单,就不展示出来了