Resource management library for Compose Multiplatform applications providing type-safe access to images, strings, fonts, and drawable assets across all platforms.
—
String array resources provide type-safe access to collections of localized strings. This is useful for lists of options, categories, labels, or any collection of related text entries that need to be localized together.
class StringArrayResource(id: String, val key: String, items: Set<ResourceItem>) : Resource(id, items)A string array resource represents an ordered collection of localized strings identified by a unique key. Each array can have different variants for different locales and configurations.
@Composable
fun stringArrayResource(resource: StringArrayResource): List<String>Loads a string array resource within a Composable context. The function automatically selects the appropriate array variant based on the current environment and locale.
Usage:
@Composable
fun CategorySelection() {
val categories = stringArrayResource(Res.array.product_categories)
LazyColumn {
items(categories) { category ->
Text(
text = category,
modifier = Modifier
.fillMaxWidth()
.clickable { onCategorySelected(category) }
.padding(16.dp)
)
}
}
}
@Composable
fun SettingsOptions() {
val options = stringArrayResource(Res.array.notification_options)
options.forEachIndexed { index, option ->
Row(
modifier = Modifier.clickable { selectOption(index) },
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
selected = selectedIndex == index,
onClick = { selectOption(index) }
)
Text(text = option, modifier = Modifier.padding(start = 8.dp))
}
}
}suspend fun getStringArray(resource: StringArrayResource): List<String>Loads a string array resource outside of a Composable context using the system's resource environment.
Usage:
suspend fun loadMenuOptions(): List<String> {
return getStringArray(Res.array.menu_options)
}
class DataLoader {
suspend fun getAvailableLanguages(): List<String> {
return getStringArray(Res.array.supported_languages)
}
suspend fun populateDropdown() {
val options = getStringArray(Res.array.dropdown_items)
dropdownAdapter.updateItems(options)
}
}suspend fun getStringArray(
environment: ResourceEnvironment,
resource: StringArrayResource
): List<String>Loads string array resources using a specific resource environment. This is useful for loading arrays in different locales or for testing purposes.
Parameters:
environment - The resource environment specifying locale, theme, and densityresource - The string array resource to loadUsage:
suspend fun getLocalizedOptions(locale: Locale): List<String> {
val environment = ResourceEnvironment(
LanguageQualifier(locale.language),
RegionQualifier(locale.country),
ThemeQualifier.LIGHT,
DensityQualifier.MDPI
)
return getStringArray(environment, Res.array.localized_options)
}
suspend fun preloadArraysForMultipleLocales() {
val locales = listOf("en", "es", "fr", "de")
val arrays = mutableMapOf<String, List<String>>()
locales.forEach { lang ->
val environment = ResourceEnvironment(
LanguageQualifier(lang),
RegionQualifier(""),
ThemeQualifier.LIGHT,
DensityQualifier.MDPI
)
arrays[lang] = getStringArray(environment, Res.array.country_names)
}
return arrays
}<string-array name="days_of_week">
<item>Monday</item>
<item>Tuesday</item>
<item>Wednesday</item>
<item>Thursday</item>
<item>Friday</item>
<item>Saturday</item>
<item>Sunday</item>
</string-array>
<string-array name="notification_frequencies">
<item>Never</item>
<item>Daily</item>
<item>Weekly</item>
<item>Monthly</item>
</string-array>
<string-array name="file_sizes">
<item>Small (< 1 MB)</item>
<item>Medium (1-10 MB)</item>
<item>Large (10-100 MB)</item>
<item>Very Large (> 100 MB)</item>
</string-array>res/
├── values/arrays.xml # Default (English)
├── values-es/arrays.xml # Spanish
├── values-fr/arrays.xml # French
├── values-de/arrays.xml # German
└── values-ja/arrays.xml # JapaneseExample Localized Arrays:
values/arrays.xml (English):
<string-array name="months">
<item>January</item>
<item>February</item>
<item>March</item>
<!-- ... -->
</string-array>values-es/arrays.xml (Spanish):
<string-array name="months">
<item>Enero</item>
<item>Febrero</item>
<item>Marzo</item>
<!-- ... -->
</string-array>@Composable
fun LanguageSelector() {
val languages = stringArrayResource(Res.array.available_languages)
var expanded by remember { mutableStateOf(false) }
var selectedIndex by remember { mutableStateOf(0) }
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = it }
) {
TextField(
value = languages[selectedIndex],
onValueChange = {},
readOnly = true,
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
languages.forEachIndexed { index, language ->
DropdownMenuItem(
text = { Text(language) },
onClick = {
selectedIndex = index
expanded = false
}
)
}
}
}
}@Composable
fun NavigationMenu() {
val menuItems = stringArrayResource(Res.array.main_menu_items)
val menuIcons = listOf(
Icons.Default.Home,
Icons.Default.Search,
Icons.Default.Profile,
Icons.Default.Settings
)
LazyColumn {
itemsIndexed(menuItems) { index, item ->
ListItem(
headlineContent = { Text(item) },
leadingContent = {
Icon(
imageVector = menuIcons[index],
contentDescription = null
)
},
modifier = Modifier.clickable {
onMenuItemClick(index)
}
)
}
}
}@Composable
fun PreferencesForm() {
val themes = stringArrayResource(Res.array.theme_options)
val frequencies = stringArrayResource(Res.array.sync_frequencies)
Column {
Text("Theme", style = MaterialTheme.typography.h6)
themes.forEachIndexed { index, theme ->
Row(verticalAlignment = Alignment.CenterVertically) {
RadioButton(
selected = selectedTheme == index,
onClick = { selectedTheme = index }
)
Text(theme)
}
}
Spacer(modifier = Modifier.height(16.dp))
Text("Sync Frequency", style = MaterialTheme.typography.h6)
frequencies.forEachIndexed { index, frequency ->
Row(verticalAlignment = Alignment.CenterVertically) {
RadioButton(
selected = selectedFrequency == index,
onClick = { selectedFrequency = index }
)
Text(frequency)
}
}
}
}String arrays are loaded and cached automatically:
@Composable
fun OptimizedArrayUsage() {
// Array is loaded once and cached
val options = stringArrayResource(Res.array.large_option_list)
// Reuse the cached array across recompositions
LazyColumn {
items(options) { option ->
Text(option)
}
}
}Best Practices:
class ArrayCache {
private val cache = mutableMapOf<StringArrayResource, List<String>>()
suspend fun getCachedArray(resource: StringArrayResource): List<String> {
return cache.getOrPut(resource) {
getStringArray(resource)
}
}
}Common Exceptions:
IllegalStateException - String array with given ID is not foundMissingResourceException - Resource file cannot be readExample Error Handling:
@Composable
fun SafeArrayLoading() {
val options = try {
stringArrayResource(Res.array.menu_options)
} catch (e: IllegalStateException) {
// Provide fallback options
listOf("Option 1", "Option 2", "Option 3")
}
options.forEach { option ->
Text(text = option)
}
}Use descriptive resource names:
Res.array.notification_types // Good
Res.array.array1 // BadKeep arrays reasonably sized:
<!-- Good: Small, manageable array -->
<string-array name="priority_levels">
<item>Low</item>
<item>Medium</item>
<item>High</item>
<item>Critical</item>
</string-array>
<!-- Consider alternatives for very large arrays -->Maintain consistent ordering:
<!-- Consistent ordering across locales -->
<string-array name="difficulty_levels">
<item>Beginner</item> <!-- Always first -->
<item>Intermediate</item> <!-- Always second -->
<item>Advanced</item> <!-- Always third -->
</string-array>Group related arrays logically:
<!-- Group by feature or screen -->
<string-array name="profile_sections">
<item>Personal Info</item>
<item>Privacy Settings</item>
<item>Notifications</item>
</string-array>
<string-array name="profile_privacy_options">
<item>Public</item>
<item>Friends Only</item>
<item>Private</item>
</string-array>Consider enum alternatives for app logic:
// For app logic, consider using enums with localized display names
enum class Priority {
LOW, MEDIUM, HIGH, CRITICAL;
@Composable
fun displayName(): String = when (this) {
LOW -> stringResource(Res.string.priority_low)
MEDIUM -> stringResource(Res.string.priority_medium)
HIGH -> stringResource(Res.string.priority_high)
CRITICAL -> stringResource(Res.string.priority_critical)
}
}Validate array consistency across locales:
Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-compose-components--components-resources