先看下效果
listview的代码
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.Scroller;
import android.widget.TextView;
public class MyListView extends ListView implements OnScrollListener {
private boolean isLoadingMore = false;// 是否 滑动到最后一行
private boolean isLoad = false;// 是否已经是在加载中了
public static final int state_down_default = 0;// 上啦的 默认状态
public static final int state_down_loosen = 1;// 上啦的 松开加载
public static final int state_down_load = 2;// 上啦的 加载中...
private int loadState = state_down_default;
private MyListViewListener loadListner;// 上啦加载的监听
private View footerView;// 加载更多布局
private TextView fTv;// 显示加载 更多提示
private int fHeight;// 底部的高度
private int startY = -1;// 开始的 y坐标
private Scroller mScroller; // 用来处理回弹的
private int htTime = 200;// 回弹的总时间 这个决定回弹的速度
public MyListView(Context context) {
this(context, null, 0);
}
public MyListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
addLoadXML();
}
public void addLoadXML() {
footerView = View.inflate(getContext(), R.layout.lv_footerview, null);
this.addFooterView(footerView);
fTv = (TextView) footerView.findViewById(R.id.tv_lv_footerview);
fTv.setText("加载更多");
footerView.measure(0, 0);
fHeight = footerView.getMeasuredHeight();
footerView.setPadding(0, -fHeight, 0, 0);// 设置隐藏
this.setOnScrollListener(this);
mScroller = new Scroller(getContext(), new DecelerateInterpolator());
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:// 按下
startY = -1;
break;
case MotionEvent.ACTION_MOVE:// 移动
if (isLoadingMore) {// 只有 滚动到最后一行才会 加载
if (!isLoad) {// 只有没有加载 才能加载
if (this.getLastVisiblePosition() == getCount() - 1) {// 并且显示到最后一条
if (startY == -1) {// 把开始位置放到这里 是因为只有当滑动到最后一行 才开始显示
// footerView
startY = (int) ev.getRawY();
}
int endY = (int) ev.getRawY();
int des = Math.abs(endY - startY);
int padding = des - fHeight;
footerView.setPadding(0, 0, 0, padding);// 设置显示的高度设置这个就会移动
if (padding > 40 && loadState == state_down_default) {// 默认状态
// 并且大于40
// 就设置成松开加载
loadState = state_down_loosen;
getRefreshDownstate();
} else if (padding <= 40
&& loadState != state_down_default) {// 不是默认状态
// 并且滑动的少与40
// 就还原成默认的
loadState = state_down_default;
getRefreshDownstate();
}
}
}
}
break;
case MotionEvent.ACTION_UP:// 离开
startY = -1;
if (isLoadingMore) {
if (loadState == state_down_loosen) {
startScroll();// 设置回弹
} else if (loadState == state_down_default) {// 如果是默认状态
// 直接隐藏footerView
footerView.setPadding(0, -fHeight, 0, 0);
}
}
break;
}
return super.onTouchEvent(ev);
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {// 这里就是每 小一次回弹 都要取设置 位置
footerView.setPadding(0, 0, 0, mScroller.getCurrY());
postInvalidate();// 更新
}
}
/**
* 刷新底部
*/
private void getRefreshDownstate() {
switch (loadState) {
case state_down_default:// 默认状态
fTv.setText("上啦加载更多");
isLoad = false;
break;
case state_down_loosen:// 松开加载
fTv.setText("松开加载");
isLoad = false;
break;
case state_down_load:// 加载中
fTv.setText("加载中...");
isLoad = true;
break;
}
}
@Override
public void onScrollStateChanged(AbsListView arg0, int scrollState) {// 判断是否在滑动
}
@Override
public void onScroll(AbsListView arg0, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {// 判断是 上滑 还是下滑
// 判断是否滚到最后一行
if (firstVisibleItem + visibleItemCount == totalItemCount
&& totalItemCount > 0) {
isLoadingMore = true;
} else {
isLoadingMore = false;
}
}
/**
* 回弹的动画
*/
public void startScroll() {
int padding = footerView.getPaddingBottom();
if (padding > 0) {// 正在加载中 并且回弹
loadState = state_down_load;
getRefreshDownstate();
mScroller.startScroll(0, padding, 0, -padding, htTime);// 这里只要把所有的
// padding
// 回弹完,就是刚好显示正在加载
invalidate();
if (loadListner != null) {
loadListner.onLoadMore();
}
}
}
/**
* 停止 加载
*/
public void stopLoadMore() {
loadState = state_down_default;
getRefreshDownstate();
footerView.setPadding(0, 0, 0, -fHeight);
}
/**
* 设置 上啦监听
*/
public void setLoadListner(MyListViewListener loadListner) {
this.loadListner = loadListner;
}
public interface MyListViewListener {
public void onLoadMore();
}
}
里面注释很详细,底部布局可以自己去修改