Найти в Дзене
Иван Петров

Экран загрузки с использованием Physics Animation

Как разработчик, я всегда стараюсь понять логику работы некоторых особенностей приложений Android и перепроектировать их в соответствии со своей логикой. Вчера я наткнулся на этот загрузочный экран приложения ShowBox, который является хорошим потоковым сервисом для фильмов и телешоу. Увидев это, я решил перестроить этот экран в соответствии с моей логикой. Я разбил эту анимацию на следующие части: В этой статье я расскажу, как я достиг этой анимации и сделал следующую демонстрацию. Спасибо Google за внедрение анимации на основе физики, представленной на Google I/O 2017, которая помогла мне выполнить первую часть с вращением. Что такое анимация, основанная на физике? До сих пор разработчики имели API для анимации, такие как Value Animators, Object Animators, где мы применяем различные интерполяторы, которые контролируют скорость изменения анимации. У всех них есть одна проблема: каждый раз приходится писать сложный код, когда приходится иметь дело со сложной анимацией, которая
Оглавление

Как разработчик, я всегда стараюсь понять логику работы некоторых особенностей приложений Android и перепроектировать их в соответствии со своей логикой.

Вчера я наткнулся на этот загрузочный экран приложения ShowBox, который является хорошим потоковым сервисом для фильмов и телешоу.

Увидев это, я решил перестроить этот экран в соответствии с моей логикой. Я разбил эту анимацию на следующие части:

  • Вращение, которое движется около координаты (0, 0) экрана.
  • Переворот этого экрана книзу.

В этой статье я расскажу, как я достиг этой анимации и сделал следующую демонстрацию.

-2

Спасибо Google за внедрение анимации на основе физики, представленной на Google I/O 2017, которая помогла мне выполнить первую часть с вращением.

Что такое анимация, основанная на физике?

До сих пор разработчики имели API для анимации, такие как Value Animators, Object Animators, где мы применяем различные интерполяторы, которые контролируют скорость изменения анимации. У всех них есть одна проблема: каждый раз приходится писать сложный код, когда приходится иметь дело со сложной анимацией, которая должна имитировать объекты реального мира. И наша реакция становится похожей на такую:

-3

Добавив анимации на основе физики, Google сделала анимации более реалистичными для своих пользователей. Эти анимации включены в библиотеки поддержку, так что они обратно совместимы до API 16. Эти типы анимации приводятся в действие с помощью силы, которая контролирует ход анимации. Вы определяете характеристики этих сил, и затем они полностью берут на себя работу с анимацией.

-4

Чтобы начать работу с этой анимацией, добавьте следующую библиотеку поддержки в блок dependencies файла build.gradle модуля приложения.

dependencies {
...
implementation "com.android.support:support-dynamic-animation:27.0.2"
}

Вам не нужно будет определять продолжительность анимации или другие параметры. Сила, которую вы зададите, позаботится об анимациях сама.

API для анимации на основе физики предоставляет два типа анимации:

Анимация пружины (Spring Animation). Эта анимация  управляется силой упругости, где скорость вашей анимации будут зависеть  от неё. Вы определяете все свойства силы, включая коэффициент  демпфирования и жесткость. API предоставляет разные типы констант, чтобы  легко их установить.
Анимация пружины (Spring Animation). Эта анимация управляется силой упругости, где скорость вашей анимации будут зависеть от неё. Вы определяете все свойства силы, включая коэффициент демпфирования и жесткость. API предоставляет разные типы констант, чтобы легко их установить.
  • Анимация броска (Fling Animation). Анимация, управляемая силой трения. Анимация броска имеет начальный импульс и постепенно замедляется. Она подчиняется законам трения, в которых сила трения пропорциональна скорости объекта, вследствие чего объект постепенно замедляется.

В этой статье я расскажу о Spring Animation, из которой я получил загрузочный экран. Достаточно говорить, перейдём к коду.

1. Создание силы упругости и её применение к SpringAnimation

SpringForce springForce = new SpringForce(0f);
relativeLayout.setPivotX(0f);
relativeLayout.setPivotY(0f);
SpringAnimation springAnimation =
new SpringAnimation(relativeLayout, DynamicAnimation.ROTATION);
springForce.setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY);
springForce.setStiffness(SpringForce.STIFFNESS_VERY_LOW);
springAnimation.setSpring(springForce);
springAnimation.setStartValue(80f);

  • В этой части кода мы инициализируем экземпляр SpringForce, передавая конструктору его положение равновесия в float.
  • Мы определяем точку опоры для RelativeLayout. Это будет (0, 0), потому что мы хотим, чтобы вращение происходило у начала экрана.
  • Начинаем определять экземпляр класса SpringAnimation, который будет принимать следующие параметры:

  • Представление, которое мы хотим анимировать.
  • DynamicAnimation, который сообщает, какое свойство представления мы хотим анимировать. В данном случае это будет вращение.

Теперь определяем свойства силы упругости. Я использовал коэффициент демпфирования DAMPING_RATIO_HIGH_BOUNCY и жесткость STIFFNESS_VERY_LOW. DAMPING_RATIO_HIGH_BOUNCY обеспечит более высокие колебания, а жесткость, равная STIFFNESS_VERY_LOW, сделает так, что объект будет медленно возвращаться в исходное состояние.

  • Теперь, наконец, мы передадим наш объект SpringForce в SpringAnimation и установим начальное значение для анимации.

2. Настройка DynamicAnimation.OnAnimationEndListener

Мы описали, что наша разметка должна вращаться около (0, 0) с заданным коэффициентом жесткости и демпфирования, и теперь нам нужно переместить разметку вниз после окончания анимации. Для этого API предоставляет нам следующие два слушателя:

  • OnAnimationUpdateListener — этот слушатель переопределяет метод onAnimationUpdate, который используется для получения изменений в процессе анимации.
  • OnAnimationEndListener — этот слушатель переопределяет метод onAnimationEnd, который используется для уведомления о завершении анимации, на которую он зарегистрирован.

В нашем случае мы регистрирует OnAnimationEndListener, чтобы переопределить метод onAnimationEnd. Затем, после окончания анимации, мы сможем перейти к перемещению макета на следующем шаге.

springAnimation.addEndListener(new DynamicAnimation.OnAnimationEndListener() {
@Override
public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value,
float velocity) {
// код перемещения будет здесь
});

3. Перемещение разметки после получения уведомления о завершении и открытие второй активности

Теперь в onAnimationEnd мы будем использовать ViewPropertyAnimator, который является ещё одним классом в Android, доступным для анимирования свойств представлений, с помощью всего нескольких строк кода.

@Override
public void onAnimationEnd(DynamicAnimation animation, boolean canceled, float value,
float velocity) {
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
float height = (float) displayMetrics.heightPixels;
float width = (float) displayMetrics.widthPixels;
relativeLayout.animate()
.setStartDelay(1)
.translationXBy(width / 2)
.translationYBy(height)
.setListener(new Animator.AnimatorListener() {
@Override public void onAnimationStart(Animator animator) {
}

@Override public void onAnimationEnd(Animator animator) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
finish();
getApplicationContext().startActivity(intent);
overridePendingTransition(0, 0);
}

@Override public void onAnimationCancel(Animator animator) {
}

@Override public void onAnimationRepeat(Animator animator) {
}
})
.setInterpolator(new DecelerateInterpolator(1f))
.start();
}

Рассмотрим шаг за шагом:

  • Сначала мы получаем объект DisplayMetrics, чтобы узнать ширину и высоту экрана устройства.
  • У RelativeLayout мы вызываем метод animate(), который возвращает ссылку на объект ViewPropertyAnimator, после чего мы можем настроить и запустить анимацию.
  • После мы вызываем метод setStartDelay(), который устанавливает задержку перед запуском анимации, затем мы устанавливаем перемещение как по оси Х, так и по оси Y, в соответствии с шириной и высотой, которые мы получили выше.
  • После настройки анимации мы также добавляем слушателя к этому ViewPropertyAnimator, в котором, когда мы получим коллбек onAnimationEnd, мы запускаем вторую активность.

Примечание: не забудьте добавить overridePendingTransition(0, 0) после вызова startActivity(), который сообщит WindowManager отключить переход по умолчанию для второй активности.

  • Наконец, на этот ViewPropertyAnimator мы устанавливаем Interpolator и запускаем с помощью метода start().

4. В конце для объекта SpringAnimation вызываем метод start()

Ваш загрузочный экран готов, теперь, скомпилировав и запустим проект, можно будет увидеть результат, показанный выше.