Images and resources
Compose Multiplatform provides a special library and Gradle plugin support for accessing resources in common code across all supported platforms. Resources are static content, such as images, fonts, and strings, which you can use from your application.
When working with resources in Compose Multiplatform, consider the current conditions:
Almost all resources are read synchronously in the caller thread. The only exceptions are raw files and all of the resources on the JS platform that are read asynchronously.
Reading big raw files, like long videos, as a stream is not supported yet. Use separate files on the user device and read them with the file system API, for example, the kotlinx-io library.
Multimodule projects are generally not supported yet, but resources in the top-level application module are available. The JetBrains team is working on adding this functionality in future releases. For now, store all resources in the main application module.
The publication of Compose Multiplatform libraries with resources is not supported yet. The JetBrains team is working on adding this functionality in future releases.
Currently, accessors are generated for the
commonMain
source set only. The JetBrains team is working on expanding this functionality in future releases.However, you can still store platform-specific resources in a platform
composeResources
directory and read them as a byte array. All resources will be included in each final app.
Setup
To access resources in your multiplatform projects:
In the
build.gradle.kts
file in thecomposeApp
directory, add a dependency to thecommonMain
source set:kotlin { sourceSets { commonMain.dependencies { implementation(compose.components.resources) } } }Create a new directory
composeResources
in thecommonMain
directory:Organize the
composeResources
directory structure according to these rules:Images should be in the
drawable
directory.Fonts should be in the
font
directory.Strings (
strings.xml
) should be in thevalues
directory.Other files with any hierarchy should be in the
files
directory.
Qualifiers
Sometimes, the same resource should be presented in different ways depending on the environment, such as locale, screen density, or interface theme. For example, you might need to localize texts for different languages or adjust images for the dark theme. For that, the library provides special qualifiers.
All resource types (except for raw files in the files
directory) support qualifiers. Apply qualifiers to directory names using a hyphen:
The library supports (in the order of priority) the following qualifiers: language, theme, and density.
Different types of qualifiers can be applied together. For example, "drawable-en-rUS-mdpi-dark" is an image for the English language in the United States region, suitable for 160 DPI screens in the dark theme.
If a resource with the requested qualifier doesn't exist, the default resource without a qualifier is used instead.
Language and regional qualifiers
The language is defined by a two-letter ISO 639-1 language code.
You can add a two-letter ISO 3166-1-alpha-2 regional code to your language code. In this case, the regional code must have a lowercase r
prefix.
The language and regional codes are case-sensitive.
Theme qualifier
You can add "light" or "dark" qualifiers. Compose Multiplatform then selects the necessary resource depending on the current system theme.
Density qualifier
You can use the following density qualifiers:
"ldpi" − 120 DPI, 0.75x density
"mdpi" − 160 DPI, 1x density
"hdpi" − 240 DPI, 1.5x density
"xhdpi" − 320 DPI, 2x density
"xxhdpi" − 480 DPI, 3x density
"xxxhdpi" − 640dpi, 4x density
The resource is selected depending on the screen density defined in the system.
Resource usage
After importing a project, a special Res
class is generated which provides access to resources. To manually generate the Res
class, run the generateComposeResClass
Gradle task.
Images
You can access drawable resources as simple images, rasterized images, or XML vectors:
To access drawable resources as
Painter
images, use thepainterResource()
function:@Composable fun painterResource(resource: DrawableResource): Painter {...}The
painterResource()
function takes a resource path and returns aPainter
value. The function works synchronously on all targets except for web. For the web target, it returns an emptyPainter
for the first recomposition that is replaced with the loaded image in subsequent recompositions.painterResource()
loads either aBitmapPainter
for rasterized image formats, such as.png
,.jpg
,.bmp
,.webp
, or aVectorPainter
for the Android XML vector drawable format.XML vector drawables have the same format as Android, except that they don't support external references to Android resources.
To access drawable resources as an
ImageBitmap
rasterized image, use theimageResource()
function:@Composable fun imageResource(resource: DrawableResource): ImageBitmap {...}To access drawable resources as an
ImageVector
XML vector, use thevectorResource()
function:@Composable fun vectorResource(resource: DrawableResource): ImageVector {...}
Here's an example of how you can access images in your Compose Multiplatform code:
Strings
Store all string resources in the strings.xml
file in the composeResources/values
directory, for example:
A static accessor is generated for each item in the strings.xml
file.
To get string resources as a String
, use the following code:
For example:
For example:
You can use special symbols in string resources:
\n
— for a new line\t
— for a tab symbol\uXXXX
— for a specific Unicode character
String templates
Currently, arguments have basic support in string resources:
There is no difference between %...s
and %...d
when using string templates with arguments from composable code, for example:
Fonts
Store custom fonts in the composeResources/font
directory as *.ttf
or *.otf
files.
To load a font as a Font
type, use the Font()
function:
For example:
Raw files
To load any raw file as a byte array, use the Res.readBytes(path)
function:
You can place raw files in the composeResources/files
directory and create any hierarchy inside it.
For example, to access raw files, use the following code:
Remote files
Only files that are part of the application are considered resources.
You can also load remote files from the internet using their URL. To load remote files, use special libraries:
What's next?
Check out the official demo project that shows how resources can be handled in a Compose Multiplatform project targeting iOS, Android, and desktop.