Как разработчик, я всегда стараюсь понять логику работы некоторых особенностей приложений Android и перепроектировать их в соответствии со своей логикой.
Вчера я наткнулся на этот загрузочный экран приложения ShowBox, который является хорошим потоковым сервисом для фильмов и телешоу.
Увидев это, я решил перестроить этот экран в соответствии с моей логикой. Я разбил эту анимацию на следующие части:
- Вращение, которое движется около координаты (0, 0) экрана.
- Переворот этого экрана книзу.
В этой статье я расскажу, как я достиг этой анимации и сделал следующую демонстрацию.
Спасибо Google за внедрение анимации на основе физики, представленной на Google I/O 2017, которая помогла мне выполнить первую часть с вращением.
Что такое анимация, основанная на физике?
До сих пор разработчики имели API для анимации, такие как Value Animators, Object Animators, где мы применяем различные интерполяторы, которые контролируют скорость изменения анимации. У всех них есть одна проблема: каждый раз приходится писать сложный код, когда приходится иметь дело со сложной анимацией, которая должна имитировать объекты реального мира. И наша реакция становится похожей на такую:
Добавив анимации на основе физики, Google сделала анимации более реалистичными для своих пользователей. Эти анимации включены в библиотеки поддержку, так что они обратно совместимы до API 16. Эти типы анимации приводятся в действие с помощью силы, которая контролирует ход анимации. Вы определяете характеристики этих сил, и затем они полностью берут на себя работу с анимацией.
Чтобы начать работу с этой анимацией, добавьте следующую библиотеку поддержки в блок dependencies файла build.gradle модуля приложения.
dependencies {
...
implementation "com.android.support:support-dynamic-animation:27.0.2"
}
Вам не нужно будет определять продолжительность анимации или другие параметры. Сила, которую вы зададите, позаботится об анимациях сама.
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()
Ваш загрузочный экран готов, теперь, скомпилировав и запустим проект, можно будет увидеть результат, показанный выше.





