带滑动反弹效果的ViewPager

参考了几篇代码,自己弄了一个带滑动反弹效果的ViewPager。
代码非常简单,主要原理就是随着手指的移动改变View的X坐标。
那么直接就简单粗暴地上代码了:

public class BounceBackViewPager extends ViewPager {

    private int currentPosition = 0;
    private boolean handleMove = false;     //是否拦截并处理了滑动
    private float preX = 0f;
    private static final float RATIO = 0.25f;//摩擦系数
    private boolean animPlaying = false;
    private float translationX;
    private static final int MIN_SCROLL_DISTANCE = 4;


    public BounceBackViewPager(Context context) {
        this(context, null);
    }

    public BounceBackViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOverScrollMode(View.OVER_SCROLL_NEVER);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                preX = ev.getX();
                currentPosition = getCurrentItem();
                translationX = getTranslationX();
                break;
            case MotionEvent.ACTION_MOVE:
                if(isOverScroll(ev)){
                    return true;
                }
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    private boolean isOverScroll(MotionEvent event){
        return (currentPosition == 0 && event.getX() > preX)
                || (getAdapter() != null && currentPosition == getAdapter().getCount() - 1 && event.getX() < preX);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (animPlaying || getAdapter() == null) {
            return super.onTouchEvent(ev);
        }
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
                recoverPosition();
                handleMove = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if(isOverScroll(ev)){
                    handleOverScrollMove(ev);
                }
            default:
                break;
        }

        return handleMove || super.onTouchEvent(ev);
    }

    private void handleOverScrollMove(MotionEvent ev){
        float nowX = ev.getX();
        float offset = nowX - preX;
        if (Math.abs(offset) > MIN_SCROLL_DISTANCE) {
            handleScroll(offset);
            preX = nowX;
        }
    }

    private void handleScroll(float offset) {
        handleMove = true;
        float tranX = getTranslationX() + offset * RATIO;
        setTranslationX(tranX);
    }

    private void recoverPosition() {
        if (getTranslationX() == translationX || !handleMove) {
            return;
        }
        ValueAnimator animator = ValueAnimator.ofFloat(getTranslationX(), translationX).setDuration(240);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float leftPosition = (float)animation.getAnimatedValue();
                setTranslationX(leftPosition);
            }

        });
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                animPlaying = false;
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animator.start();
        animPlaying = true;
    }

}

如果需要Kotlin版本的代码,可以看 这里

ps: 使用中如果有任何问题,欢迎讨论。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值