Как добавить векторную графику с разной плотностью (Views)

Основные понятия и реализация Jetpack Compose

В Android Studio есть инструмент Vector Asset Studio, который позволяет добавлять значки Material Design и импортировать файлы SVG и PSD в проект в качестве ресурсов класса VectorDrawable. Использование класса VectorDrawable вместо битовых карт позволяет уменьшить размер APK, поскольку один и тот же файл можно изменить размер для экранов с разной плотностью пикселей без потери качества изображения. Для более ранних версий Android, которые не поддерживают класс VectorDrawable, инструмент Vector Asset Studio может во время сборки преобразовать векторные изображения в растровые разных размеров для каждой плотности экрана.

Об инструменте Vector Asset Studio

Инструмент Vector Asset Studio добавляет в проект векторную графику в виде XML-файла, описывающего изображение. Поддерживать один XML-файл может быть проще, чем обновлять несколько растровых изображений с разным разрешением.

Android 4.4 (уровень API 20) и более ранние версии не поддерживают класс VectorDrawable. Если в вашем приложении задан один из этих уровней API, то при работе с Vector Asset Studio вы можете либо генерировать файлы PNG (по умолчанию), либо использовать метод обратной совместимости в AndroidX.

Для обратной совместимости инструмент Vector Asset Studio генерирует растровые изображения класса VectorDrawable. Векторные и растровые объекты упаковываются вместе в APK. Вы можете ссылаться на класс VectorDrawable как на Drawable в коде Java или @drawable в коде XML. При запуске приложения соответствующее векторное или растровое изображение будет отображаться автоматически в зависимости от уровня API.

Обратная совместимость в AndroidX

Для этого способа требуется AndroidX 1.0 или более поздней версии и плагин Android для Gradle 3.2 или более поздней версии. Используются только классы VectorDrawable. Класс VectorDrawableCompat в AndroidX позволяет поддерживать VectorDrawable в Android 2.1 (уровень API 7) и более поздних версиях.

Прежде чем использовать Vector Asset Studio, добавьте в файл build.gradle следующую строку:

Яркий

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.7.1'
}

Kotlin

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

dependencies {
    implementation("androidx.appcompat:appcompat:1.7.1")
}

Для обратной совместимости также необходимо использовать методы кодирования AndroidX, например атрибут app:srcCompat вместо android:src для классов VectorDrawable. Подробную информацию можно найти в статье AndroidX.

Добавление класса VectorDrawable в макет

В файле макета можно настроить любой виджет, связанный со значками, например ImageButton, ImageView и т. д., чтобы он указывал на векторный объект. Например, в следующем макете показан векторный объект, отображаемый на кнопке:

Рис. 1. Класс VectorDrawable, показанный на кнопке в макете.

Чтобы отобразить векторный рисунок на виджете, как показано на рисунке:

  1. Откройте проект и импортируйте векторный объект.

    В этом примере используется проект для телефона или планшета, созданный с помощью мастера создания проектов.

  2. В окне Project (Проект) в режиме Android view (Просмотр Android) дважды нажмите на XML-файл макета, например content_main.xml.

  3. Перейдите на вкладку Дизайн, чтобы открыть Редактор макетов.

  4. Перетащите виджет ImageButton из окна Palette (Палитра) в редактор макета.

  5. В диалоговом окне Resources (Ресурсы) выберите Drawable (Графический объект) на панели слева, а затем выберите импортированный векторный графический объект. Нажмите ОК.

    Класс VectorDrawable появится на макете ImageButton.

  6. Чтобы изменить цвет изображения на цвет акцента, заданный в теме, в окне Properties (Свойства) найдите свойство tint (оттенок) и нажмите … .

  7. В диалоговом окне Resources (Ресурсы) на панели слева выберите Color (Цвет), а затем – colorAccent. Нажмите ОК.

    Цвет изображения изменится на цвет акцента в макете.

Если в проекте используется AndroidX, код ImageButton должен выглядеть примерно так:

<ImageButton
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:srcCompat="@drawable/ic_build_black_24dp"
  tools:layout_editor_absoluteX="11dp"
  tools:layout_editor_absoluteY="225dp"
  android:id="@+id/imageButton"
  android:tint="@color/colorAccent" />

Если в проекте не используется AndroidX, код класса VectorDrawable будет выглядеть так: android:src="@drawable/ic_build_black_24dp".

Ссылка на класс VectorDrawable в коде

Обычно в коде можно ссылаться на ресурс класса VectorDrawable стандартным способом. При запуске приложения автоматически отображается соответствующее векторное или растровое изображение в зависимости от уровня API:

  • В большинстве случаев вы можете ссылаться на класс VectorDrawable как на @drawable в XML-коде или Drawable в коде Java.

    Например, следующий XML-код макета применяет изображение к представлению:

    <ImageView
      android:layout_height="wrap_content"
      android:layout_width="wrap_content"
      android:src="@drawable/myimage" />

    Следующий код извлекает изображение как Drawable:

    Kotlin

    val drawable = resources.getDrawable(R.drawable.myimage, theme)

    Java

    Resources res = getResources();
    Drawable drawable = res.getDrawable(R.drawable.myimage, getTheme());

    Метод getResources() находится в классе Context, который применяется к объектам пользовательского интерфейса, таким как действия, фрагменты, макеты, представления и т. д.

  • Если в вашем приложении используется AndroidX (даже если в файле build.gradle нет инструкции vectorDrawables.useSupportLibrary = true), вы также можете ссылаться на класс VectorDrawable с помощью инструкции app:srcCompat. Пример:

    <ImageView
      android:layout_height="wrap_content"
      android:layout_width="wrap_content"
      app:srcCompat="@drawable/myimage" />
  • Иногда может потребоваться привести прорисовываемый ресурс к его точному классу, например, когда вам нужно использовать определенные функции класса VectorDrawable. Для этого можно использовать следующий код:

    Kotlin

    if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.LOLLIPOP) {
      val vectorDrawable = drawable as VectorDrawable
    } else {
      val bitmapDrawable = drawable as BitmapDrawable
    }

    Java

    if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.LOLLIPOP) {
      VectorDrawable vectorDrawable = (VectorDrawable) drawable;
    } else {
      BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
    }

Доступ к ресурсам VectorDrawable можно получить только из основного потока.

В Android 5.0 (уровень API 21) и более поздних версиях можно использовать класс AnimatedVectorDrawable для анимации свойств класса VectorDrawable. С помощью AndroidX вы можете использовать класс AnimatedVectorDrawableCompat для анимации класса VectorDrawable в Android 3.0 (уровень API 11) и более поздних версиях. Подробнее о том, как анимировать графику…