Объекты на экране часто нужно перемещать в результате взаимодействия с пользователем или фоновой обработки. Вместо того чтобы сразу обновлять положение объекта, из-за чего он будет мигать, перемещаясь из одной области в другую, используйте анимацию, чтобы переместить его из начального положения в конечное.
Один из способов изменить положение объектов на экране – использовать ObjectAnimator. Вы указываете конечную позицию, в которой должен оказаться объект, а также длительность анимации. Вы также можете использовать интерполяторы времени, чтобы управлять ускорением или замедлением анимации.
Как изменить положение представления с помощью ObjectAnimator
API ObjectAnimator позволяет изменять свойства представления с заданной продолжительностью.
Он содержит статические методы для создания экземпляров ObjectAnimator в зависимости от того, какой тип атрибута вы анимируете. Чтобы изменить положение представлений на экране, используйте атрибуты translationX и translationY.
Вот пример ObjectAnimator, который перемещает область просмотра в положение на расстоянии 100 пикселей от левого края экрана за 2 секунды:
Kotlin
ObjectAnimator.ofFloat(view, "translationX", 100f).apply { duration = 2000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f); animation.setDuration(2000); animation.start();
В этом примере используется метод ObjectAnimator.ofFloat(), поскольку значения сдвига должны быть числами с плавающей запятой. Первый параметр –
это представление, которое вы хотите анимировать. Второй параметр – это свойство, которое вы анимируете. Поскольку представление должно перемещаться по горизонтали, используется свойство translationX. Последний параметр – это конечное значение анимации. В этом примере значение 100 указывает на позицию, которая находится на расстоянии 100 пикселей от левого края экрана.
Следующий метод определяет длительность анимации в миллисекундах. В этом примере анимация длится две секунды (2000 миллисекунд).
Последний метод запускает анимацию, которая обновляет положение представления на экране.
Подробнее о том, как использовать ObjectAnimator, рассказывается в статье Как создавать анимацию с помощью ObjectAnimator.
Как добавить криволинейное движение
Хотя использовать ObjectAnimator удобно, по умолчанию он перемещает вид по прямой линии между начальной и конечной точками. В Material Design кривые используются для пространственного перемещения объектов на экране и синхронизации анимации. Использование криволинейного движения придает вашему приложению более материальный вид, делая ваши анимации более интересными.
Выбирайте свой путь
Класс ObjectAnimator содержит конструкторы, позволяющие анимировать координаты с помощью двух или более свойств одновременно, а также пути. Например, в следующем аниматоре используется объект Path для анимации свойств X и Y представления:
Kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val path = Path().apply { arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true) } val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply { duration = 2000 start() } } else { // Create animator without using curved path }
Java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Path path = new Path(); path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true); ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); animator.setDuration(2000); animator.start(); } else { // Create animator without using curved path }
Вот как выглядит анимация дуги:
Рисунок 1. Анимация криволинейного пути.
Interpolator – это реализация кривой плавности. Дополнительную информацию о концепции кривых плавности можно найти в документации по Material Design. Interpolator определяет, как рассчитываются определенные значения в анимации в зависимости от времени. В системе есть XML-ресурсы для трех основных кривых в спецификации Material Design:
@interpolator/fast_out_linear_in.xml@interpolator/fast_out_slow_in.xml@interpolator/linear_out_slow_in.xml
Используйте PathInterpolator
Класс PathInterpolator – это интерполятор, представленный в Android 5.0 (API 21). Она основана на кривой Безье или объекте Path. В примерах для Android в документации по смягчению в Material Design используется PathInterpolator.
PathInterpolator имеет конструкторы, основанные на разных типах кривых Безье.
Все кривые Безье имеют начальную и конечную точки, зафиксированные в (0,0) и (1,1) соответственно. Другие аргументы конструктора зависят от типа создаваемой кривой Безье.
Например, для квадратичной кривой Безье нужны только координаты X и Y одной контрольной точки:
Kotlin
val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { PathInterpolator(0.67f, 0.33f) } else { LinearInterpolator() }
Java
Interpolator myInterpolator = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { myInterpolator = new PathInterpolator(0.67f, 0.33f); } else { myInterpolator = new LinearInterpolator(); }
Это создает кривую замедления, которая начинается быстро и замедляется по мере приближения к концу.
Конструктор кубической кривой Безье также имеет фиксированные начальную и конечную точки, но требует двух контрольных точек:
Kotlin
val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f) } else { LinearInterpolator() }
Java
Interpolator myInterpolator = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f); } else { myInterpolator = new LinearInterpolator(); }
Это реализация кривой замедления emphasized decelerate из Material Design.
Для более точного управления можно использовать произвольное значение Path:
Kotlin
val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val path = Path().apply { moveTo(0.0f, 0.0f) cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f) } PathInterpolator(path) } else { LinearInterpolator() }
Java
Interpolator myInterpolator = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Path path = new Path(); path.moveTo(0.0f, 0.0f); path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f); myInterpolator = new PathInterpolator(path); } else { myInterpolator = new LinearInterpolator(); }
В результате получается такая же кривая, как и в примере с кубической кривой Безье, но с использованием Path.
Вы также можете определить интерполятор пути как ресурс XML:
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:controlX1="0.5"
android:controlY1="0.7"
android:controlX2="0.1f"
android:controlY2="1.0f"/>
Созданный объект PathInterpolator можно передать методу Animator.setInterpolator(). Animator использует интерполятор, чтобы определить время или кривую пути при запуске.
Kotlin
val animation = ObjectAnimator.ofFloat(view, "translationX", 100f).apply { interpolator = myInterpolator start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f); animation.setInterpolator(myInterpolator); animation.start();