在 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:
android VIewpager How to achieve the bound effect.
How do disable paging by swiping with finger in ViewPager but still be able to swipe programmatically?
Add “Rubber Band” effect in android while changing background of application.
第三个 post 的答案提到了这种方法,但没有提供任何细节。
有谁知道我们如何将 BounceInterpolator
与 PageTransformer
结合起来? 似乎 是解决此问题的有机且连贯的方法,但它是否可能呢?或者对此有其他合理的解决方案吗?
参考文献:
N.B:
应该可以简单地通过组合 Interpolator
和 PageTransformer
来实现弹性/弹跳动画效果,而无需扩展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
触发。当然在这种情况下我们还有另一个注意事项,但这种方法似乎更有希望。
我想显示一个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:
android VIewpager How to achieve the bound effect.
How do disable paging by swiping with finger in ViewPager but still be able to swipe programmatically?
Add “Rubber Band” effect in android while changing background of application.
第三个 post 的答案提到了这种方法,但没有提供任何细节。
有谁知道我们如何将 BounceInterpolator
与 PageTransformer
结合起来? 似乎 是解决此问题的有机且连贯的方法,但它是否可能呢?或者对此有其他合理的解决方案吗?
参考文献:
N.B:
应该可以简单地通过组合 Interpolator
和 PageTransformer
来实现弹性/弹跳动画效果,而无需扩展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
触发。当然在这种情况下我们还有另一个注意事项,但这种方法似乎更有希望。