π¦ Resources π¦
Resources are used everywhere, especially when we try to customize the application (e.g., localization, dark-theme, responsive...):
- π layouts
- π¬ strings (texts)
- π¨ colors
- βοΈ dimensions
- πΌοΈ drawables (images)
- πΊοΈ mipmap (icons)
- ...
You can manage them from the Resources Manager.
From the code, there is a dynamically created class R
that we use to access our resources:
R.layout.fragment_blank
R.id.some_id
- ...
Add @LayoutRes
, @DrawableRes
, @StringRes
... before a variable, parameter, or attribute to enforce the type of resource.
fun loadIcon(@DrawableRes drawableId: Int) { /* ... */ }
Drawables πΌοΈ
A drawable is an image in a format such as PNG, JPG, or SVG.
Add an image
- Open the Resource Manager
- Navigate to "Drawable"
- Click on "+"
- Import
Add an icon
- Open the Resource Manager
- Navigate to "Drawable"
- Click on "+"
- Vector Asset
- Click on the (android icon) next to "clip art"
- Select an icon
β οΈ It's recommended to use the Material Icons library instead.
Localization π€
Android automatically detects the language of the operating system and loads the appropriate language if available, otherwise fallback to the default language.
The default language is defined inside res/values/strings.xml.
Add a new language
- Open the Resource Manager
- Navigate to "String"
- Click on "+" and "New resource file"
- Give the FileName "strings"
- Select "Locale" in "Available qualifiers"
- Click on ">>"
- Select the language you want. You may select a region too.
- This will open an empty file
- Copy-paste inside the default language file.
Now, you can set translations for the new locale.
To add translations, you should use the Translations Editor (see the "open edit" at the top of any language file).
Edit strings.xml
This is a dictionary: a key is associated with a value.
<string name="key">value</string>
Inside another XML, you can reference a string with @string
<TextView
android:text="@string/key" />
Or, in the code
var value = getString(R.string.key)
// same (from resources)
var value = resources.getString(R.string.key)
// same (from a view)
var value = view.context.getString(R.string.key)
Parameters
Android uses String.format to parse the value, so you can pass parameters, as you would to printf in C.
<string name="price">The price is %s</string>
Inside the code
var value = getString(R.string.price, "$3")
Plurals
You can provide variants according to the number of elements.
<plurals name="count">
<item quantity="zero">0</item>
<item quantity="one">1</item>
<item quantity="two">2</item>
<item quantity="few">few</item>
<item quantity="many">many</item>
<item quantity="other">unknown</item>
</plurals>
Then, you need to pass a quantity. β οΈ NOTE that the quantity is used along the locale to determine which "item" will be used. For instance, in English, only one, and others will be used.
resources.getQuantityString(R.plurals.count, 0)
Utilities
Currency
You can return the appropriate currency from an int/a double with
val amount = NumberFormat.getCurrencyInstance().format(1300.74)
// USA/CA: "$1,300.74"
// UK: "Β£1,300.74"
// FR: "1 300,74β¬"
Dates
See SimpleDateFormat.
// ex: "ss" = show seconds on two digits
val formatter = SimpleDateFormat("ss", Locale.getDefault())
val calendar = Calendar.getInstance()
val xxx = formatter.format(calendar.time)
Other resources π§Έ
Arrays
Arrays are lists of hard-coded values such as a list of countries. Go to Resources Manager > Arrays, and create a new one.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="str_array">
<item>Toto</item>
</string-array>
<integer-array name="int_array">
<item>5</item>
</integer-array>
</resources>
In the code
// β¨ .toList() is optional, you can use arrays "as if"
val stringArray = resources.getStringArray(R.array.str_array).toList()
val intArray = resources.getIntArray(R.array.int_array).toList()
Dimensions
Every folder in res
may have multiples "copies" for different devices. For instance, if there is a view for large-screen devices, it will be used instead of the view made of "every" device.
It's also a better practice to avoid hard-coded padding/margins/..., and instead, add them inside a dimens.xml
, then use @dimens/key
.
So, you can have one dimens.xml
per category of device screen size.