自定义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   vus520  阅读(281)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架

导航

< 2011年5月 >
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 1 2 3 4
5 6 7 8 9 10 11
点击右上角即可分享
微信分享提示