我正在研究当前项目中的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;
}