在 ViewPager 中实现弹性/弹跳动画效果的最佳方法是什么?

What is the best way to achieve an elastic / bounce animation effect in ViewPager?

我想显示一个ViewPager with a bounce / elastic sliding effect. I suppose that this is possible using some combination of a PageTransformer and a BounceInterpolator

我不知道的是如何。到目前为止,我一直无法实现这一目标。

PageTransformer 的典型示例如下所示:

public class TypicalPageTransformer implements ViewPager.PageTransformer {

    @Override
    public void transformPage(View view, float position) {

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);

        } else if (position <= 0) { // [-1,0]
            // Use the default slide transition when moving to the left page
            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(1);
            view.setScaleY(1);

        } else if (position <= 1) { // (0,1]
            // Fade the page out.
            view.setAlpha(1 - position);

            // Counteract the default slide transition
            view.setTranslationX(pageWidth * -position);

            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

问题是,我们如何为 ViewPager 的动画带来 Interpolator (of any kind) into the picture here? Where do we get the Animation 对象,以便为其设置 Interpolator

我已经提到了以下 posts:

第三个 post 的答案提到了这种方法,但没有提供任何细节。

有谁知道我们如何将 BounceInterpolatorPageTransformer 结合起来? 似乎 是解决此问题的有机且连贯的方法,但它是否可能呢?或者对此有其他合理的解决方案吗?

参考文献:

N.B:

应该可以简单地通过组合 InterpolatorPageTransformer 来实现弹性/弹跳动画效果,而无需扩展ViewPager。其他方法也欢迎,但请提供详细的代码解决方案,而不仅仅是提纲。

可以使用fakeDragBy方法来实现这个效果:

 viewPager.beginFakeDrag();
viewPager.fakeDragBy(offset); //offset in pixels. 
viewPager.endFakeDrag();

或者你可以使用这个方法:

private int animFactor;
private ValueAnimator animator = new ValueAnimator();

private void animateViewPager(final ViewPager pager, final int offset, final int delay) {
    if (!animator.isRunning()) {
        animator.removeAllUpdateListeners();
        animator.removeAllListeners();
        //Set animation
        animator.setIntValues(0, -offset);
        animator.setDuration(delay);
        animator.setRepeatCount(1);
        animator.setRepeatMode(ValueAnimator.RESTART);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer value = animFactor * (Integer) animation.getAnimatedValue();
                if (!pager.isFakeDragging()) {
                    pager.beginFakeDrag();
                }
                pager.fakeDragBy(value);
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {

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

            @Override
            public void onAnimationEnd(Animator animation) {
                pager.endFakeDrag();
            }

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

在 Java Class 中仅使用此 :

animateViewPager(pager, 10, 1000);

看看this library,也许对你有帮助。

我不确定 PageTransformer 是达到上述效果的最佳方式。请注意,这种转换在两个滑动方向上都是相同的,因为接收到的位置并不知道我们是从左向右滑动还是从左向右滑动。并且您可能不希望视图的两个相对侧弹跳,而只想要应用拉力的一个。第二,更重要的是,PageTransformer 框架是由用户的手势驱动的,而不是由稳定的系统时钟驱动的。结果 - 我们无法控制淡入淡出阶段的持续时间(用户松开 his/her 手指时的阶段)并实现平滑的行为(因为通常滴答是在非单调变化的位置传递的,这在很大程度上取决于触摸速度).

因此,使用标准 ValueAnimator API 会更好,它将由 OnPageChangeListener 触发。当然在这种情况下我们还有另一个注意事项,但这种方法似乎更有希望。