Resources generation in Kotlin Multiplatform.
// build.gradle.kts (project)
buildscript {
dependencies {
classpath("io.github.skeptick.libres:gradle-plugin:1.2.2")
}
}
// build.gradle.kts (module)
plugins {
id("io.github.skeptick.libres")
}
libres {
generatedClassName = "MainRes" // "Res" by default
generateNamedArguments = true // false by default
baseLocaleLanguageCode = "ru" // "en" by default
camelCaseNamesForAppleFramework = false // false by default
}
// build.gradle.kts (module)
kotlin {
commonMain {
dependencies {
implementation("io.github.skeptick.libres:libres-compose:1.2.2")
}
}
}
This artifact provides painterResource
function that can be used
to get Painter
from io.github.skeptick.libres.Image
in common code.
- Android, JVM, iOS, MacOS and JS in Kotlin Multiplatform projects.
- Pure Android or JVM projects with Kotlin.
Kotlin | 1.6.20+ |
Android | 4.1+ (API level 16) |
Android Gradle Plugin | 7.0+ |
iOS | 13+ (when using vector icons) |
If you aren't reusing images in iOS then this condition is optional.
pod install
is called,
so bundles directory must exist at this time.
You won't see this issue if your .podspec
is in .gitignore
in any case it's best to be safe with this hook in your Podfile.
Suppose your Kotlin Framework is added like this:
pod 'umbrella', :path => '../common/umbrella/umbrella.podspec'
Then this hook will look like this:
pre_install do |installer|
FileUtils.mkdir_p(installer.sandbox.root.to_s + '/../../common/umbrella/build/generated/libres/apple/libres-bundles')
end
Resources must be stored in {yourSourceSetName}/libres
Multiplatform:
├── commonMain
│ ├── kotlin
│ └── libres
│ ├── images
│ │ ├── vector_image.svg
│ │ └── raster_image.png
│ └── strings
│ ├── strings_en.xml
│ └── strings_ru.xml
Android or JVM:
├── main
│ ├── java
│ └── libres
│ ├── images
│ │ ├── vector_image.svg
│ │ └── raster_image.png
│ └── strings
│ ├── strings_en.xml
│ └── strings_ru.xml
Strings are stored in usual for Android form in xml
files.
The file postfix must contain language code for which these strings are intended. E.g.: my_app_strings_en.xml
For each of languages you can create several files and they will be merged during compilation.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="simple_string">Hello!</string>
<string name="string_with_arguments">Hello ${name}!</string>
<plurals name="plural_string">
<item quantity="one">resource</item>
<item quantity="other">resources</item>
</plurals>
</resources>
Kotlin:
MainRes.string.simple_string
MainRes.string.string_with_arguments.format(name = "John")
MainRes.string.plural_string.format(5)
Swift:
MainRes.shared.string.simple_string
// or MainRes.shared.string.simpleString if `camelCaseNamesForAppleFramework` enabled
Note In this example
MainRes.string.simple_string
will return a string, so for better localization support it's not recommended to store the value. Get it directly at the place where it's displayed in UI. This seems familiar but ability to work directly with strings instead of resource IDs can be misused.
Supported formats:
- PNG
- JPG
- WEBP (Android 4.3+, iOS 14+)
- SVG (iOS 13+)
For Android SVGs are converted to vector drawable, for other platforms they copied as is.
The image filename can contain modifiers in parentheses listed through underscores.
orig
Used for iOS. Marks image as
Original
(similar toRender As: Original Image
in XCode Assets Manager). Recommended for multicolor images.
size
Applies to bitmaps. Reduces image resolution to specified size.
- For Android generate images from mdpi to xxxhdpi (where mdpi is 1:1 in pixels to specified size)
- For iOS generate images from @1x to @3x (where @1x is 1:1 in pixels to specified size)
- For JVM and JS a single image of specified size is generated.
Filename examples:
some_hd_image_(100).jpg
app_logo_(orig).svg
my_colorful_bitmap_(orig)_(150).png
Kotlin:
MainRes.image.some_hd_image
MainRes.image.app_logo
MainRes.image.my_colorful_bitmap
Swift:
MainRes.shared.image.some_hd_image
// or MainRes.shared.image.someHdImage if `camelCaseNamesForAppleFramework` enabled
I'm pretty sure your picture is multicolor JPG/SVG with opaque background.
This happens because UIKit recolors this image with accent color.
Solution: add (orig) modifier to image filename, e.g.: my_image_(orig).png
To obtain bundle of PNG images with different resolutions (mdpi-xxxhdpi for Android and @1x-@3x for iOS) do following steps:
- Export image from Figma with x4 scale (it matches to the biggest used size — xxxhdpi on Android)
- Put it to
libres/images
package - Remember the biggest side value of image represented in Figma
- Rename image with the value of the biggest side:
pic.png -> pic_(orig)_({side_value}).png or pic_({side_value}).png
Sample: Image size in Figma is 240x89. Final image name is pic_(orig)_(240).png