Анимация графических ресурсов

Попробуйте Compose
Jetpack Compose – это рекомендуемый набор инструментов для создания пользовательского интерфейса в Android. Узнайте, как использовать анимацию в Compose.
Рисунок 1. Класс AnimatedDrawable.

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

Первый вариант – использовать AnimationDrawable. Это позволяет указать несколько статических графических файлов, которые будут отображаться по одному, создавая анимацию. Второй вариант – использовать класс AnimatedVectorDrawable, который позволяет анимировать свойства класса VectorDrawable.

Используйте AnimationDrawable

Один из способов создать анимацию – загрузить последовательность прорисовываемых ресурсов, как в киноленте. Класс AnimationDrawable является основой для таких анимаций.

Вы можете определить кадры анимации в своем коде с помощью API класса AnimationDrawable, но проще определить их с помощью одного XML-файла, в котором перечислены кадры, составляющие анимацию. XML-файл для этого типа анимации находится в каталоге res/drawable/ проекта для Android. В этом случае инструкции задают порядок и длительность каждого кадра в анимации.

XML-файл состоит из элемента <animation-list> в качестве корневого узла и серии дочерних узлов <item>, каждый из которых определяет кадр – прорисовываемый ресурс и его длительность. Ниже приведен пример XML-файла для анимации Drawable.

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
    <item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
    <item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>

Эта анимация состоит из трех кадров. Если задать для атрибута android:oneshot списка значение true, то анимация будет воспроизведена один раз, а затем остановится на последнем кадре. Если для свойства android:oneshot задано значение false, анимация будет повторяться.

Если вы сохраните этот XML-код как rocket_thrust.xml в каталоге res/drawable/ проекта, то сможете добавить его в качестве фонового изображения в View, а затем вызвать start(), чтобы воспроизвести его. Ниже приведен пример действия, в котором анимация добавляется в ImageView, а затем воспроизводится при касании экрана.

Kotlin

private lateinit var rocketAnimation: AnimationDrawable

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main)

    val rocketImage = findViewById<ImageView>(R.id.rocket_image).apply {
        setBackgroundResource(R.drawable.rocket_thrust)
        rocketAnimation = background as AnimationDrawable
    }

    rocketImage.setOnClickListener({ rocketAnimation.start() })
}

Java

AnimationDrawable rocketAnimation;

public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
  rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
  rocketAnimation = (AnimationDrawable) rocketImage.getBackground();

  rocketImage.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        rocketAnimation.start();
      }
  });
}

Важно отметить, что метод start(), вызываемый для AnimationDrawable, нельзя вызвать во время метода onCreate() вашего Activity, поскольку AnimationDrawable ещё не полностью прикреплен к окну. Чтобы анимация воспроизводилась сразу, без взаимодействия с пользователем, вызовите ее из метода onStart() в Activity. Он вызывается, когда Android показывает представление на экране.

Подробную информацию о синтаксисе XML, а также доступных тегах и атрибутах можно найти в статье Ресурсы анимации.

Используйте AnimatedVectorDrawable

Класс VectorDrawable позволяет масштабировать изображение без потери качества. Класс AnimatedVectorDrawable (и AnimatedVectorDrawableCompat для обратной совместимости) позволяет анимировать свойства векторного графического объекта, например поворачивать его или изменять данные контура, чтобы превратить его в другое изображение.

Обычно анимированные векторные объекты определяются в трех XML-файлах:

  • Класс VectorDrawable с элементом <vector> в res/drawable/.
  • Анимированный класс VectorDrawable с элементом <animated-vector> в res/drawable/.
  • Один или несколько аниматоров объектов с элементом <objectAnimator> в res/animator/.

Анимированные классы VectorDrawable могут анимировать атрибуты элементов <group> и <path>. Элемент <group> определяет набор контуров или подгрупп, а элемент <path> – контуры, которые нужно нарисовать.

При определении векторного объекта, который вы хотите анимировать, используйте атрибут android:name, чтобы присвоить уникальное имя группам и путям. Это позволит ссылаться на них из определений аниматора. Пример:

res/drawable/vectordrawable.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600">
    <group
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="v"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>

Определение анимированного класса VectorDrawable ссылается на группы и пути в классе VectorDrawable по их именам:

res/drawable/animatorvectordrawable.xml

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
  android:drawable="@drawable/vectordrawable" >
    <target
        android:name="rotationGroup"
        android:animation="@animator/rotation" />
    <target
        android:name="v"
        android:animation="@animator/path_morph" />
</animated-vector>

Определения анимации представляют собой объекты ObjectAnimator или AnimatorSet. Первый аниматор в этом примере поворачивает целевую группу на 360 градусов:

res/animator/rotation.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
  <objectAnimator
      android:duration="6000"
      android:propertyName="rotation"
      android:valueFrom="0"
      android:valueTo="360" />
</set>

Второй аниматор в этом примере преобразует контур класса VectorDrawable из одной формы в другую. Контуры должны быть совместимы для морфинга: они должны иметь одинаковое количество команд и одинаковое количество параметров для каждой команды.

res/animator/path_morph.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
        android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
        android:valueType="pathType" />
</set>

Вот полученный AnimatedVectorDrawable:

Рисунок 2. AnimatedVectorDrawable.

Предварительный просмотр анимированного векторного объекта рисования (AVD)

Инструмент Animated Vector Drawable в Android Studio позволяет просматривать анимированные прорисовываемые ресурсы. Этот инструмент позволяет просматривать ресурсы <animation-list>, <animated-vector> и <animated-selector> в Android Studio и упрощает настройку пользовательских анимаций.

Пользователь просматривает и воспроизводит анимацию в Android Studio.
Рисунок 3. Инструмент Animated Vector Drawable в Android Studio.

Дополнительную информацию можно найти в документации по API для AnimatedVectorDrawable.