当listview滑动到顶部和底部的时候就停住了,这时候我们想要让listview产生上下弹动的效果但不刷新数据,通过结合晚上现有数据刷新的例子花了点时间终于做出来啦,直接拿来用就可以了 废话不多说,上源码:
如果需要直接引用自定义的PaddingListView就OK了
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.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Scroller;
public class PaddingListView extends ListView implements OnScrollListener {
private float mLastY = -1; // save event y
private Scroller mScroller; // used for scroll back
private OnScrollListener mScrollListener; // user's scroll listener
private PaddingView mHeaderView, mFooterView;
private int mHeaderViewHeight; // header view's height
private boolean mEnablePullRefresh = true;
private boolean mPullRefreshing = false; // is refreashing.
private boolean mIsFooterReady = false;
private int mTotalItemCount;
// for mScroller, scroll back from header or footer.
private int mScrollBack;
private final static int SCROLLBACK_HEADER = 0;
private final static int SCROLLBACK_FOOTER = 1;
private final static int SCROLL_DURATION = 400; // scroll back duration
private final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px
private final static float OFFSET_RADIO = 5.0f; // support iOS like pull
// feature.
/**
* @param context
*/
public PaddingListView(Context context) {
super(context);
initWithContext(context);
}
public PaddingListView(Context context, AttributeSet attrs) {
super(context, attrs);
initWithContext(context);
}
public PaddingListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initWithContext(context);
}
private void initWithContext(Context context) {
mScroller = new Scroller(context, new DecelerateInterpolator());
super.setOnScrollListener(this);
mHeaderView = new PaddingView(context);
addHeaderView(mHeaderView);
mFooterView = new PaddingView(context);
}
@Override
public void setAdapter(ListAdapter adapter) {
if (mIsFooterReady == false) {
mIsFooterReady = true;
addFooterView(mFooterView);
}
super.setAdapter(adapter);
}
private void invokeOnScrolling() {
if (mScrollListener instanceof OnXScrollListener) {
OnXScrollListener l = (OnXScrollListener) mScrollListener;
l.onXScrolling(this);
}
}
private void updateHeaderHeight(float delta) {
mHeaderView.setBottomMargin((int) delta
+ mHeaderView.getHeight());
setSelection(0); // scroll to top each time
}
/**
* reset header view's height.
*/
private void resetHeaderHeight() {
int height = mHeaderView.getHeight();
if (height == 0) // not visible.
return;
if (mPullRefreshing && height <= mHeaderViewHeight) {
return;
}
int finalHeight = 0; // default: scroll back to dismiss header.
if (mPullRefreshing && height > mHeaderViewHeight) {
finalHeight = mHeaderViewHeight;
}
mScrollBack = SCROLLBACK_HEADER;
mScroller.startScroll(0, height, 0, finalHeight - height,
SCROLL_DURATION);
invalidate();
}
private void updateFooterHeight(float delta) {
int height = mFooterView.getBottomMargin() + (int) delta;
mFooterView.setBottomMargin(height);
}
private void resetFooterHeight() {
int bottomMargin = mFooterView.getBottomMargin();
if (bottomMargin > 0) {
mScrollBack = SCROLLBACK_FOOTER;
mScroller.startScroll(0, bottomMargin, 0, -bottomMargin,
SCROLL_DURATION);
invalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mLastY == -1) {
mLastY = ev.getRawY();
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
final float deltaY = ev.getRawY() - mLastY;
mLastY = ev.getRawY();
if (getFirstVisiblePosition() == 0
&& (mHeaderView.getHeight() > 0 || deltaY > 0)) {
// the first item is showing, header has shown or pull down.
updateHeaderHeight(deltaY / OFFSET_RADIO);
invokeOnScrolling();
} else if (getLastVisiblePosition() == mTotalItemCount - 1
&& (mFooterView.getBottomMargin() > 0 || deltaY < 0)) {
// last item, already pulled up or want to pull up.
updateFooterHeight(-deltaY / OFFSET_RADIO);
}
break;
default:
mLastY = -1; // reset
if (getFirstVisiblePosition() == 0) {
// invoke refresh
if (mEnablePullRefresh
&& mHeaderView.getHeight() > mHeaderViewHeight) {
mPullRefreshing = true;
}
resetHeaderHeight();
}
if (getLastVisiblePosition() == mTotalItemCount - 1) {
// invoke load more.
resetFooterHeight();
}
break;
}
return super.onTouchEvent(ev);
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
if (mScrollBack == SCROLLBACK_HEADER) {
mHeaderView.setBottomMargin(mScroller.getCurrY());
} else {
mFooterView.setBottomMargin(mScroller.getCurrY());
}
postInvalidate();
invokeOnScrolling();
}
super.computeScroll();
}
@Override
public void setOnScrollListener(OnScrollListener l) {
mScrollListener = l;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (mScrollListener != null) {
mScrollListener.onScrollStateChanged(view, scrollState);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// send to user's listener
mTotalItemCount = totalItemCount;
if (mScrollListener != null) {
mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,
totalItemCount);
}
}
/**
* you can listen ListView.OnScrollListener or this one. it will invoke
* onXScrolling when header/footer scroll back.
*/
public interface OnXScrollListener extends OnScrollListener {
public void onXScrolling(View view);
}
}
class PaddingView extends LinearLayout {
private LinearLayout mContainer;
public PaddingView(Context context) {
super(context);
initView(context);
}
public PaddingView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public void setBottomMargin(int height) {
if (height < 0) return;
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContainer
.getLayoutParams();
lp.height = height;
mContainer.setLayoutParams(lp);
}
public int getBottomMargin() {
return mContainer.getHeight();
}
private void initView(Context context) {
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, 0);
mContainer = new LinearLayout(context);
addView(mContainer, lp);
}
}