Использование мультиплатформенных ресурсов в приложении
После того как вы настроили ресурсы для проекта, соберите проект, чтобы сгенерировать специальный класс Res, предоставляющий доступ к ресурсам. Чтобы повторно сгенерировать класс Res и все средства доступа к ресурсам, снова соберите проект или повторно импортируйте его в IDE.
После этого вы сможете использовать сгенерированный класс для доступа к настроенным мультиплатформенным ресурсам из кода или внешних библиотек.
Подробнее о следующих темах:
Настройка генерации класса средств доступа: как сделать его общедоступным, назначить ему пакет или генерировать безусловно.
-
Работа с определенными типами ресурсов:
Ресурсы Drawable, например обычные изображения, растровые изображения или векторная графика XML.
Векторные значки Android XML из библиотеки Material Symbols.
Строки, в том числе обычные строки, шаблоны, массивы и строки для множественного числа.
Файлы Raw и преобразование массивов байтов в изображения.
Доступ к ресурсам, сопоставленным со строковыми идентификаторами.
Использование мультиплатформенных ресурсов в качестве ресурсов Android.
-
Работа с ресурсами, специфичными для веб-платформы:
Предварительная загрузка ресурсов с помощью функций браузера и API предварительной загрузки.
Автоматический подбор шрифта для отсутствующих символов.
Работа с внешними ресурсами: из внешних библиотек, удаленными файлами и ресурсами Java.
Импорт сгенерированного класса
Чтобы использовать подготовленные ресурсы, импортируйте сгенерированный класс, например:
import project.shared.generated.resources.Res import project.shared.generated.resources.example_image
Здесь:
project— имя вашего проектаshared— модуль, в котором расположены каталоги ресурсовRes— имя сгенерированного класса по умолчаниюexample_image— имя файла изображения в каталогеcomposeResources/drawable(например,example_image.png).
Настройка генерации класса средств доступа
Вы можете настроить сгенерированный класс Res в соответствии со своими потребностями с помощью параметров Gradle.
В блоке compose.resources {} файла build.gradle.kts можно указать несколько параметров, влияющих на генерацию класса Res для проекта. Пример конфигурации:
compose.resources {
publicResClass = false
packageOfResClass = "me.sample.library.resources"
generateResClass = auto
}
Значение
publicResClass, равноеtrue, делает сгенерированный классResобщедоступным. По умолчанию сгенерированный класс имеет модификатор доступа internal.Параметр
packageOfResClassпозволяет назначить сгенерированному классуResопределенный пакет (для доступа из кода, а также для изоляции в итоговом артефакте). По умолчанию Compose Multiplatform назначает классу пакет{group name}.{module name}.generated.resources.Значение
generateResClass, равноеalways, заставляет проект безусловно генерировать классRes. Это может быть полезно, если библиотека ресурсов доступна только транзитивно. По умолчанию Compose Multiplatform использует значениеauto, чтобы генерировать классRes, только если в текущем проекте есть явная зависимостьimplementationилиapiот библиотеки ресурсов.
Использование ресурсов
Изображения
Вы можете обращаться к ресурсам Drawable как к обычным изображениям, растровым изображениям или векторной графике XML. Изображения SVG поддерживаются на всех платформах, кроме Android.
-
Чтобы обращаться к ресурсам Drawable как к изображениям
Painter, используйте функциюpainterResource():@Composable fun painterResource(resource: DrawableResource): Painter {...}Функция
painterResource()принимает путь к ресурсу и возвращает значениеPainter. На всех целевых платформах, кроме веб-платформы, функция работает синхронно. На веб-платформе она возвращает пустойPainterпри первой рекомпозиции; в последующих рекомпозициях он заменяется загруженным изображением.painterResource()загружает либоBitmapPainterдля растровых форматов изображений, например.png,.jpg,.bmp,.webp, либоVectorPainterдля формата векторных Drawable Android XML.Векторные Drawable XML имеют тот же формат, что и Android, за исключением того, что они не поддерживают внешние ссылки на ресурсы Android.
-
Чтобы обращаться к ресурсам Drawable как к растровым изображениям
ImageBitmap, используйте функциюimageResource():@Composable fun imageResource(resource: DrawableResource): ImageBitmap {...} -
Чтобы обращаться к ресурсам Drawable как к векторной графике Android XML
ImageVector, используйте функциюvectorResource():@Composable fun vectorResource(resource: DrawableResource): ImageVector {...}
Вот пример доступа к изображениям из кода Compose Multiplatform:
Image(
painter = painterResource(Res.drawable.my_image),
contentDescription = null
)
Отрисовка изображений на холсте
Чтобы самостоятельно нарисовать изображение из ресурса, а не отображать его с помощью компонуемого элемента Image(), загрузите его как ImageBitmap или ImageVector и используйте в DrawScope:
Чтобы нарисовать
ImageBitmap, используйтеDrawScope.drawImage().Чтобы нарисовать
ImageVector, создайтеPainterс помощьюrememberVectorPainter()и используйтеPainter.draw().
Указывайте смещения и размеры в DrawScope, в пикселях:
val myImageRaster = imageResource(Res.drawable.my_image_raster)
val myImageVectorPainter = rememberVectorPainter(vectorResource(Res.drawable.my_image_vector))
Canvas(modifier = Modifier.fillMaxSize()) {
// Inside the lambda, `this` is an instance of `DrawScope`, which provides `drawImage()` and `translate()`
drawImage(image = myImageRaster, topLeft = Offset(20f, 20f))
translate(left = 20f, top = myImageRaster.height + 40f) {
// The `Painter.draw()` function uses both the `DrawScope` and `Painter` as receivers
with(myImageVectorPainter) {
draw(Size(200f, 200f))
}
}
}
Значки
Вы можете использовать векторные значки Android XML из библиотеки Material Symbols:
Откройте галерею значков Google Fonts, выберите значок, перейдите на вкладку Android и нажмите Download.
Добавьте загруженный файл значка XML в каталог
drawableмультиплатформенных ресурсов.-
Откройте файл значка XML и задайте для
android:fillColorзначение#000000. Удалите все остальные атрибуты Android, специфичные для настройки цвета, напримерandroid:tint.До:
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="960" android:viewportHeight="960" android:tint="?attr/colorControlNormal"> <path android:fillColor="@android:color/white" android:pathData="..."/> </vector>После:
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="960" android:viewportHeight="960"> <path android:fillColor="#000000" android:pathData="..."/> </vector> Соберите проект, чтобы сгенерировать средства доступа к ресурсам, или позвольте плагину Kotlin Multiplatform для IDE сделать это автоматически.
Вот пример доступа к значку и настройки его цветов с помощью параметра colorFilter в коде Compose Multiplatform:
Image(
painter = painterResource(Res.drawable.ic_sample_icon),
contentDescription = "Sample icon",
modifier = Modifier.size(24.dp),
colorFilter = ColorFilter.tint(Color.Blue)
)
Строки
Храните все строковые ресурсы в XML-файлах в каталогах composeResources/values. Для каждого элемента в каждом файле генерируется статическое средство доступа.
Compose Multiplatform поддерживает сокращенный синтаксис в стиле Emmet для добавления строковых ресурсов, массивов строк и строк для множественного числа непосредственно в XML-файлы. Например, если ввести test{Example} или s.test{Example} в strings.xml и нажать Tab, запись автоматически развернется в <string name="test">Example</string>.
Чтобы узнать, как локализовать строки для разных языковых стандартов, ознакомьтесь с руководством по локализации строк.
Обычные строки
Чтобы сохранить обычную строку, добавьте в XML элемент <string>:
<resources>
<string name="app_name">My awesome app</string>
<string name="title">Some title</string>
</resources>
Чтобы получить строковые ресурсы в виде String, используйте следующий код:
@Composable
fun stringResource(resource: StringResource): String {...}
@Composable
fun stringResource(resource: StringResource, vararg formatArgs: Any): String {...}
Например:
Text(stringResource(Res.string.app_name))
suspend fun getString(resource: StringResource): String suspend fun getString(resource: StringResource, vararg formatArgs: Any): String
Например:
coroutineScope.launch {
val appName = getString(Res.string.app_name)
}
В строковых ресурсах можно использовать специальные символы:
\n— символ новой строки\t— символ табуляции\uXXXX— определенный символ Unicode
Вам не нужно экранировать специальные символы XML, например «@» или «?», как это требуется для строк Android.
Шаблоны строк
В настоящее время для строковых ресурсов доступна базовая поддержка аргументов. Создавая шаблон, используйте формат %<number> для размещения аргументов в строке и добавляйте суффикс $d или $s, чтобы указать, что это заполнитель переменной, а не обычный текст. Например:
<resources>
<string name="str_template">Hello, %2$s! You have %1$d new messages.</string>
</resources>
Создав и импортировав ресурс шаблона строки, вы можете обратиться к нему, передав аргументы для заполнителей в правильном порядке:
Text(stringResource(Res.string.str_template, 100, "User_name"))
Между суффиксами $s и $d нет разницы, другие суффиксы не поддерживаются. Вы можете поместить заполнитель %1$s в строковый ресурс и использовать его для отображения дробного числа, например:
Text(stringResource(Res.string.str_template, "User_name", 100.1f))
Массивы строк
Вы можете сгруппировать связанные строки в массив и автоматически обращаться к ним как к объекту List<String>:
<resources>
<string name="app_name">My awesome app</string>
<string name="title">Some title</string>
<string-array name="str_arr">
<item>item \u2605</item>
<item>item \u2318</item>
<item>item \u00BD</item>
</string-array>
</resources>
Чтобы получить соответствующий список, используйте следующий код:
@Composable
fun stringArrayResource(resource: StringArrayResource): List<String> {...}
Например:
val arr = stringArrayResource(Res.array.str_arr) if (arr.isNotEmpty()) Text(arr[0])
suspend fun getStringArray(resource: StringArrayResource): List<String>
Например:
coroutineScope.launch {
val appName = getStringArray(Res.array.str_arr)
}
Множественное число
Если интерфейс показывает количество объектов, может понадобиться поддержка грамматического согласования для разных чисел одного и того же объекта (одна книга, много книг и так далее), чтобы не создавать программно не связанные между собой строки.
Концепция и базовая реализация в Compose Multiplatform такие же, как и для строк количества в Android. Дополнительную информацию о рекомендациях и особенностях использования множественного числа в проекте см. в документации Android.
Поддерживаются варианты
zero,one,two,few,manyиother. Обратите внимание: не для каждого языка учитываются все варианты. Например,zeroигнорируется в английском языке, поскольку не отличается от других форм множественного числа, кроме формы для числа 1. Чтобы определить, какие различия действительно важны для языка, обратитесь к специалисту по языку.Часто можно обойтись без строк количества, используя нейтральные формулировки, например «Книги: 1», если это не ухудшает взаимодействие с пользователем.
Чтобы определить множественное число, добавьте элемент <plurals> в любой файл .xml каталога composeResources/values. Набор plurals — это простой ресурс, на который ссылаются по атрибуту name (а не по имени XML-файла). Поэтому ресурсы plurals можно объединять с другими простыми ресурсами в одном XML-файле внутри одного элемента <resources>:
<resources>
<string name="app_name">My awesome app</string>
<string name="title">Some title</string>
<plurals name="new_message">
<item quantity="one">%1$d new message</item>
<item quantity="other">%1$d new messages</item>
</plurals>
</resources>
Чтобы обратиться к форме множественного числа как к String, используйте следующий код:
@Composable
fun pluralStringResource(resource: PluralStringResource, quantity: Int): String {...}
@Composable
fun pluralStringResource(resource: PluralStringResource, quantity: Int, vararg formatArgs: Any): String {...}
Например:
Text(pluralStringResource(Res.plurals.new_message, 1, 1))
suspend fun getPluralString(resource: PluralStringResource, quantity: Int): String suspend fun getPluralString(resource: PluralStringResource, quantity: Int, vararg formatArgs: Any): String
Например:
coroutineScope.launch {
val appName = getPluralString(Res.plurals.new_message, 1, 1)
}
Шрифты
Храните пользовательские шрифты в каталоге composeResources/font. Compose Multiplatform поддерживает форматы шрифтов TTF, OTF, TTC и вариативные шрифты на всех платформах. Форматы WOFF и WOFF2 доступны только в веб-версии и macOS.
Чтобы загрузить шрифт как тип Font, используйте компонуемую функцию Font():
@Composable
fun Font(
resource: FontResource,
weight: FontWeight = FontWeight.Normal,
style: FontStyle = FontStyle.Normal
): Font
Например:
В веб-приложениях специальные символы, например эмодзи и символы арабского письма, поддерживаются автоматически благодаря автоматическому подбору шрифта, который при необходимости загружает шрифты Noto.
Если вам нужно полностью контролировать используемый шрифт, включите в пакет определенный шрифт и зарегистрируйте его вручную с помощью API предварительной загрузки.
Файлы Raw
Чтобы загрузить любой файл Raw в виде массива байтов, используйте функцию Res.readBytes(path):
suspend fun readBytes(path: String): ByteArray
Файлы Raw можно размещать в каталоге composeResources/files и создавать внутри него любую иерархию.
Например, для доступа к файлам Raw используйте следующий код:
var bytes by remember {
mutableStateOf(ByteArray(0))
}
LaunchedEffect(Unit) {
bytes = Res.readBytes("files/myDir/someFile.bin")
}
Text(bytes.decodeToString())
coroutineScope.launch {
val bytes = Res.readBytes("files/myDir/someFile.bin")
}
Преобразование массивов байтов в изображения
Если файл, который вы читаете, является растровым изображением (JPEG, PNG, BMP, WEBP) или векторным изображением XML, можно использовать следующие функции для преобразования его в объект ImageBitmap или ImageVector, подходящий для компонуемого элемента Image().
Получите доступ к файлам Raw, как показано в разделе «Файлы Raw», а затем передайте результат компонуемому элементу:
// bytes = Res.readBytes("files/example.png")
Image(bytes.decodeToImageBitmap(), null)
// bytes = Res.readBytes("files/example.xml")
Image(bytes.decodeToImageVector(LocalDensity.current), null)
На всех платформах, кроме Android, также можно преобразовать файл SVG в объект Painter:
// bytes = Res.readBytes("files/example.svg")
Image(bytes.decodeToSvgPainter(LocalDensity.current), null)
Сгенерированные карты ресурсов и строковых идентификаторов
Для удобства Compose Multiplatform также сопоставляет ресурсы со строковыми идентификаторами. Обращаться к ним можно, используя имя файла в качестве ключа:
val Res.allDrawableResources: Map<String, DrawableResource> val Res.allStringResources: Map<String, StringResource> val Res.allStringArrayResources: Map<String, StringArrayResource> val Res.allPluralStringResources: Map<String, PluralStringResource> val Res.allFontResources: Map<String, FontResource>
Пример передачи сопоставленного ресурса компонуемому элементу:
Image(painterResource(Res.allDrawableResources["compose_multiplatform"]!!), null)
Мультиплатформенные ресурсы Compose в качестве ресурсов Android
Начиная с Compose Multiplatform 1.7.0 все мультиплатформенные ресурсы упаковываются в ресурсы Android. Благодаря этому Android Studio может создавать предварительный просмотр компонуемых элементов Compose Multiplatform в исходных наборах Android.
Использование мультиплатформенных ресурсов в качестве ресурсов Android также позволяет напрямую обращаться к ним из WebView и компонентов медиаплеера Android, поскольку к ресурсам можно перейти по простому пути, например Res.getUri("files/index.html").
Пример компонуемого элемента Android, отображающего HTML-страницу ресурса со ссылкой на изображение из ресурсов:
В примере используется следующий простой HTML-файл:
Оба файла ресурсов в этом примере находятся в исходном наборе commonMain:
Взаимодействие с другими библиотеками и ресурсами
Доступ к мультиплатформенным ресурсам из внешних библиотек
Если вы хотите обрабатывать мультиплатформенные ресурсы с помощью других библиотек, подключённых к проекту, можно передавать в эти API пути к файлам, специфичные для платформы. Чтобы получить путь, специфичный для платформы, вызовите функцию Res.getUri(), указав путь проекта к ресурсу:
val uri = Res.getUri("files/my_video.mp4")
Теперь, когда переменная uri содержит абсолютный путь к файлу, любая внешняя библиотека может использовать этот путь для доступа к файлу удобным для неё способом.
Для задач, специфичных для Android, мультиплатформенные ресурсы также упаковываются как ресурсы Android.
Удалённые файлы
В контексте библиотеки ресурсов ресурсами считаются только файлы, являющиеся частью приложения.
Для загрузки удалённых файлов из интернета по URL можно использовать специализированные библиотеки:
Если вы вручную скачиваете изображение или считываете его байты, воспользуйтесь функциями декодирования библиотеки ресурсов, чтобы преобразовать их. Пример загрузки изображений из сети в настольном приложении см. в разделе Использование изображений в Compose Multiplatform для настольных приложений.
Если вы самостоятельно скачиваете изображение или считываете его байты, преобразуйте их в изображение с помощью функций декодирования библиотеки ресурсов. Пример загрузки изображений из сети в настольном приложении см. в руководстве по использованию изображений в Compose Multiplatform для настольных приложений.
Использование ресурсов Java
Хотя ресурсы Java можно использовать с Compose Multiplatform, они не поддерживают расширенные возможности платформы: генерируемые средства доступа, поддержку нескольких модулей, локализацию и так далее. Чтобы воспользоваться этими возможностями, рассмотрите возможность полного перехода на библиотеку мультиплатформенных ресурсов.
В Compose Multiplatform 1.7.0 API ресурсов, доступный в пакете compose.ui, объявлен устаревшим. Если вам по-прежнему нужно работать с ресурсами Java, скопируйте в проект следующую реализацию, чтобы код продолжал работать после обновления до Compose Multiplatform 1.7.0 или более поздней версии:
Что дальше?
Посмотрите официальный демонстрационный проект, в котором показана работа с ресурсами в проекте Compose Multiplatform для iOS, Android и настольных платформ.
Узнайте, как управлять средой ресурсов приложения, например темой и языком внутри приложения.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/multiplatform/compose-multiplatform-resources-usage.html