Ответ 1
В этой анимации есть две фазы. Сначала он масштабирует оси X и Y, а второй уменьшает масштаб. Итак, мы можем разделить их на два AnimatorSet
и последовательно воспроизводить их.
Ключевой момент анимации - найти соответствующий интерполятор для второго AnimatorSet
, потому что он не является стандартным.
Посмотрите, мы хотим, чтобы fab перевыполнил, затем недосчитался, а затем, наконец, доработал до указанного значения в аниматоре.
К счастью, очень удобно PathInterpolator
, что создаст для нас интерполятор с предоставленным Path
.
Path path = new Path();
path.moveTo(0.0f, 0.0f);
path.lineTo(0.5f, 1.3f);
path.lineTo(0.75f, 0.8f);
path.lineTo(1.0f, 1.0f);
PathInterpolator pathInterpolator = new PathInterpolator(path);
Итак, создадим первую анимацию:
final float from = 1.0f;
final float to = 1.3f;
ObjectAnimator scaleX = ObjectAnimator.ofFloat(fab, View.SCALE_X, from, to);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(fab, View.SCALE_Y, from, to);
ObjectAnimator translationZ = ObjectAnimator.ofFloat(fab, View.TRANSLATION_Z, from, to);
AnimatorSet set1 = new AnimatorSet();
set1.playTogether(scaleX, scaleY, translationZ);
set1.setDuration(100);
set1.setInterpolator(new AccelerateInterpolator());
set1.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
fab.setImageResource(isActive ? R.drawable.heart_active : R.drawable.heart_passive);
fab.setBackgroundTintList(ColorStateList.valueOf(isActive ? colorActive : colorPassive));
isActive = !isActive;
}
});
Мы масштабируем как x, y. Кроме того, мы меняем z-перевод на соответствующий эффект теней. Когда анимация заканчивается, мы хотим изменить состояние fab (цвет сердца и фона).
Теперь давайте создадим анимацию для установки:
ObjectAnimator scaleXBack = ObjectAnimator.ofFloat(fab, View.SCALE_X, to, from);
ObjectAnimator scaleYBack = ObjectAnimator.ofFloat(fab, View.SCALE_Y, to, from);
ObjectAnimator translationZBack = ObjectAnimator.ofFloat(fab, View.TRANSLATION_Z, to, from);
AnimatorSet set2 = new AnimatorSet();
set2.playTogether(scaleXBack, scaleYBack, translationZBack);
set2.setDuration(300);
set2.setInterpolator(pathInterpolator);
См. здесь, мы использовали PathInterpolator
, который мы создали ранее.
Мы хотим последовательно воспроизводить эти два AnimatorSet
:
final AnimatorSet set = new AnimatorSet();
set.playSequentially(set1, set2);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
fab.setClickable(true);
}
@Override
public void onAnimationStart(Animator animation) {
fab.setClickable(false);
}
});
Кроме того, мы хотим отключить клики на Fab во время анимации. Поэтому мы включаем/выключаем его в зависимости от состояния анимации.
Наконец, мы запускаем анимацию, когда происходит клик:
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
set.start();
}
});
Результат: