自定义ListView下拉弹起效果

在实现ListView下拉弹起效果,最重要的是如何监听到ListView的底部及顶部,AbstractListViewtrackMotionScroll(int,int)方法中,分析出ListView是如何判断滑动到底部及顶部的方法。

private boolean isHeader(int deltay) {
   int firstTop = getChildAt(0).getTop();
   int effectivePaddingTop = getListPaddingTop();
   int spaceAbove = effectivePaddingTop - firstTop;
   return getFirstVisiblePosition() == 0&&spaceAbove<=0&&deltay<0;
 }
 private boolean isButtom(int deltay) {
    int lastBottom = getChildAt(getChildCount() - 1).getBottom();
    int effectivePaddingBottom = getListPaddingBottom();
    return getLastVisiblePosition() == (getCount() - 1)&&lastBottom<=(getHeight()-effectivePaddingBottom)&&deltay>0;
 }
 

通过以上两个方法可以判断ListView是否滑动到底部及顶部。
但是为了实现弹起效果,必须用到scrollBy()和scrollTo()两个方法。具体实现代码如下:

import android.content.Context;
 import android.os.Handler;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.widget.ListView;
 import android.widget.Scroller;
 public class MyListView extends ListView {
 private Context mContext;
 private Scroller mScroller;
 private int mLastMotionY = 0;
 public MyListView(Context context, AttributeSet attrs, int defStyle) {
   super(context, attrs, defStyle);
   // TODO Auto-generated constructor stub
 }
 public MyListView(Context context, AttributeSet attrs) {
   super(context, attrs);
   this.mContext = context;
   mScroller = new Scroller(mContext);
 }
 public MyListView(Context context) {
   super(context);
   // TODO Auto-generated constructor stub
 }
 @Override
 public void computeScroll() {
   if (mScroller.computeScrollOffset()) {
    scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    postInvalidate();
   }
 }
 @Override
 public boolean dispatchTouchEvent(MotionEvent event) {
   // TODO Auto-generated method stub
   int y = (int) event.getY();
   switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
    if (mScroller != null) {
     if (!mScroller.isFinished()) {
      mScroller.abortAnimation();
     }
    }
    mLastMotionY = y;
    break;
   case MotionEvent.ACTION_MOVE:
    int deltay = (int) (mLastMotionY - y);
    mLastMotionY = y;
    if (isButtom(deltay)) {
     setVerticalScrollBarEnabled(false);
     scrollBy(0, deltay);
     return true;
    }
    if (isHeader(deltay)) {
     setVerticalScrollBarEnabled(false);
     scrollBy(0, deltay);
     return true;
    }
    break;
   case MotionEvent.ACTION_UP:
    mLastMotionY = 0;
    if (getScrollY()!=0) {
     mScroller.startScroll(0, getScrollY(), 0, -getScrollY(), 1000);
     invalidate();
     handler.sendEmptyMessageDelayed(0, 500);
     return true;
    }
    break;
   default:
    break;
   }
   return super.dispatchTouchEvent(event);
 }
 private boolean isHeader(int deltay) {
   int firstTop = getChildAt(0).getTop();
   int effectivePaddingTop = getListPaddingTop();
   int spaceAbove = effectivePaddingTop - firstTop;
   return getFirstVisiblePosition() == 0&&spaceAbove<=0&&deltay<0;
 }
 private boolean isButtom(int deltay) {
    int lastBottom = getChildAt(getChildCount() - 1).getBottom();
    int effectivePaddingBottom = getListPaddingBottom();
    return getLastVisiblePosition() == (getCount() - 1)&&lastBottom<=(getHeight()-effectivePaddingBottom)&&deltay>0;
 }

 Handler handler = new Handler(){
   public void handleMessage(android.os.Message msg) {
    int what = msg.what;
    switch (what) {
    case 0:
     setVerticalScrollBarEnabled(true);
     invalidate();
     break;
    default:
     break;
    }
   };
 };
 }

下载地址

posted on 2011-05-04 11:05  vus520  阅读(280)  评论(0编辑  收藏  举报

导航