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