Как добиться плавной анимации встряски - PullRequest
0 голосов
/ 21 сентября 2018

Я исследую анимацию 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;
    }
...