仿IOS阻尼回弹效果的ListView

上次给他们发过一个这样的东西,不过上次的那个代码好像是发错了有点问题,非常抱歉,不是老手,请大家见谅。


话就不多说了,直接上代码。


大家一起交流交流学习学习




import android.app.ActionBar.Tab;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.Scroller;


public class ListViewEx extends ListView implements OnScrollListener {


    private float lastX;
    private float lastY;
    private final static float RATIO = 2.25f;
    private int startY;
    private int state;


    private boolean isRecored;


    private Scroller mScroller;


    public static final int STATUS_FOOTER_IDLE = 0;
    public static final int STATUS_FOOTER_LOADING = 1;
    public static final int STATUS_FOOTER_DONE = 2;
    public static final int STATUS_FOOTER_NET_ERROR = 3;
    public static final int STATUS_FOOTER_REFRESHING = 4;
    private int footerStatus = STATUS_FOOTER_IDLE;


    private int lastPos, totalCount;


    private boolean isBottom = false;
    private boolean isTop = true;


    public int getFooterStatus() {
        return footerStatus;
    }


    public void setFooterStatus(int footerStatus) {
        this.footerStatus = footerStatus;
    }


    public int getState() {
        return state;
    }


    public ListViewEx(Context context) {
        this(context, true);
    }


    public ListViewEx(Context context, boolean isEnabled) {
        super(context);
        init(context);
    }


    public ListViewEx(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }


    private void init(Context context) {
        mScroller = new Scroller(getContext());
        setOnScrollListener(this);
    }


    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {


    }


    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {


        if (firstVisibleItem == 0) {
            isTop = true;
        } else {
            isTop = false;
        }


        lastPos = view.getLastVisiblePosition();
        totalCount = totalItemCount;
        if (lastPos == totalCount - 1) {
            isBottom = true;


        } else {
            isBottom = false;
        }


    }


    float lastDx;
    float lastDy;
    boolean record = false;


    public boolean dispatchTouchEvent(MotionEvent ev) {
        float x = ev.getX();
        float y = ev.getY();


        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                record = false;
                lastDx = x;
                lastDy = y;


                break;
            case MotionEvent.ACTION_MOVE: {
                final float deltaX = Math.abs(x - lastDx);
                final float deltaY = Math.abs(y - lastDy);


                if (deltaX > 0 && deltaX > deltaY) {
                    record = true;
                } else {
                    record = false;
                }
            }
                break;


            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                isRecored = false;
                break;


        }
        return super.dispatchTouchEvent(ev);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {


        float x = ev.getX();
        float y = ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:


                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                final float deltaX = Math.abs(x - lastX);
                final float deltaY = Math.abs(y - lastY);
                if (deltaX > 0 && deltaX > deltaY) {
                    return false;


                } else {
                    float curY = ev.getY();


                    // if (curY - lastY > 0 && getScrollY() == 0) {
                    // top = true;
                    // bottom = false;
                    // } else if (curY - lastY < 0 && getScrollY() == getChildAt(0).getMeasuredHeight()) {
                    // top = false;
                    // bottom = false;
                    // } else {
                    // top = false;
                    // bottom = true;
                    //
                    // }
                    getParent().requestDisallowInterceptTouchEvent(false);
                }


                break;


            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                requestDisallowInterceptTouchEvent(false);
                break;
        }


        return super.onInterceptTouchEvent(ev);


    }


    private int distance;


    @Override
    public void computeScroll() {


        // 先判断mScroller滚动是否完成
        if (mScroller.computeScrollOffset()) {


            // 这里调用View的scrollTo()完成实际的滚动
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());


            // 必须调用该方法,否则不一定能看到滚动效果
            postInvalidate();
        }
        super.computeScroll();
    }


    @Override
    public boolean onTouchEvent(MotionEvent ev) {


        switch (ev.getAction()) {


            case MotionEvent.ACTION_DOWN:


                if (!isRecored) {
                    isRecored = true;
                    startY = (int) ev.getY();
                }
                break;
            case MotionEvent.ACTION_UP:
                if (isTop || isBottom) {
                    changeViewByState();
                }


                isRecored = false;


                break;


            case MotionEvent.ACTION_MOVE:


                int tempY = (int) ev.getY();
                if (!isRecored) {
                    isRecored = true;
                    startY = tempY;
                }
                if (isBottom && isTop) {
                    distance = (int) ((tempY - startY) / RATIO);
                    smoothTo(0, -distance);


                    // smoothTo(0, -distance);
                } else {
                    if (isTop) {
                        if (tempY - lastY > 0) {
                            distance = (int) ((tempY - startY) / RATIO);
                            smoothTo(0, -distance);


                            // smoothTo(0, -distance);
                        }
                    } else if (isBottom) {
                        if (tempY - lastY < 0) {
                            distance = (int) ((tempY - startY) / RATIO);
                            smoothTo(0, -distance);


                            // smoothTo(0, -distance);
                        }
                    }
                }


                // else if (tempY - lastY < 0 && getScrollY() == getChildAt(0).getMeasuredHeight()) {
                // distance =
                // (int) ((tempY - startY) / RATIO);
                // smoothTo(0, -distance);
                // }
                break;


            default:
                break;
        }
        return super.onTouchEvent(ev);
    }


    private final void smoothScrollToNormal() {
        smoothTo(0, 0);
    }


    private void smoothTo(int fx, int fy) {
        int dx = fx - mScroller.getFinalX();
        int dy = fy - mScroller.getFinalY();
        mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
        invalidate();
    }


    private void changeViewByState() {
        smoothScrollToNormal();
        distance = 0;
    }


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值