如何实现Buttery Smooth ViewPager Shake动画

时间:2018-09-21 14:53:11

标签: android android-viewpager android-animation

我正在研究当前项目中的Android ViewPager动画。

我想为我的用户提供与ViewPager相关的功能。

我想要的效果是使ViewPager从左到右“摇动”以部分显示所选页面的相邻页面。

当用户选择第一页(F)时,我会在F和F + 1之间“摇动”。

当用户选择最后一页(L)时,我会在L和L-1之间“摇动”。

否则,当用户选择任何其他页面(X)时,我会在X-1,X和X + 1之间“摇动”。

我尝试了以下方法,但均未获得令人满意的结果。

Fake drag using screen density to calculate shake distance and valueAnimator and ObjectAnimator.

Animating ViewPager.PageTransformer.

我无法获得令人满意的“摇动”效果。

我想获得一种Spring Dampening动画样式。

FakeDrag最接近,虽然效果不可靠,但似乎在我第一次启动动画时无法正常工作。

即使FakeDrag也无法在页面滑动之间提供所需的平滑抖动。

我想在视图寻呼机上使用基于物理的动画,但看不到如何。

是否可以实现所需的动画?

更新

我开发了此代码,该代码可以达到预期的效果,但是它的JANKY!

 @Override
    protected void onResume() {
        super.onResume();

        final Handler handler = new Handler();
        handler.postDelayed(() -> animateViewPager(ANIMATION_OFFSET, ANIMATION_DURATION), ANIMATION_DELAY);
    }


  /**
     * @param offset
     * @param duration
     */
    private void animateViewPager(final int offset, final int duration) {
        if (animator.isRunning()) {
            return;
        }

        animator.removeAllUpdateListeners();
        animator.removeAllListeners();

        animator.setIntValues(0, -offset);
        animator.setDuration(duration);
        animator.setRepeatCount(getRepeatCount());
        animator.setRepeatMode(ValueAnimator.RESTART);
        animator.addUpdateListener(constructUpdateListener());

        animator.addListener(constructAnimatorListener());
        animator.start();

    }

    /**
     *
     * @return
     */
    private Animator.AnimatorListener constructAnimatorListener() {
        return new AnimatorListenerAdapter() {

            @Override
            public void onAnimationStart(final Animator animation) {
                animFactor = 1;
            }

            @Override
            public void onAnimationEnd(final Animator animation) {
                viewPager.endFakeDrag();
                if (xAnimation == null) {
                    xAnimation = createSpringAnimation(viewPager, SpringAnimation.X, 0, SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_HIGH_BOUNCY);
                } else {
                    xAnimation.cancel();
                }

                viewPager.animate().x(viewPager.getWidth() * 0.1f).setDuration(0).start();
                xAnimation.start();
            }

            @Override
            public void onAnimationRepeat(final Animator animation) {
                animFactor = -1;
            }
        };
    }

    /**
     * @return
     */
    private int getRepeatCount() {
        if (isOnlyPage()) {
            return 0;
        }

        if (isFirstListItem()) {
            return REPEAT_ONCE;
        }

        if (isLastListItem()) {
            return REPEAT_ONCE;
        }

        return REPEAT_TWICE;
    }

    @SuppressWarnings("StatementWithEmptyBody")
    private ValueAnimator.AnimatorUpdateListener constructUpdateListener() {
        return animation -> {
            final Integer value = animFactor * (Integer) animation.getAnimatedValue();
            if (viewPager.isFakeDragging()) {
            } else {
                viewPager.beginFakeDrag();
            }
            viewPager.fakeDragBy(value);
        };
    }

    /**
     * @param view
     * @param property
     * @param finalPosition
     * @param stiffness
     * @param dampingRatio
     * @return
     */
    private SpringAnimation createSpringAnimation(final View view, final DynamicAnimation.ViewProperty property, final float finalPosition, final float stiffness, final float dampingRatio) {
        final SpringAnimation animation = new SpringAnimation(view, property);
        final SpringForce springForce = new SpringForce(finalPosition);
        springForce.setStiffness(stiffness);
        springForce.setDampingRatio(dampingRatio);
        animation.setSpring(springForce);
        return animation;
    }

0 个答案:

没有答案