I want to change my app language dynamically, without the need to restart the Activity
for the results to take effect. What I am doing now is to add a mutable Boolean
state that is switch and is used by all Text
elements.
To change the language I call the following code inside the clickable callback (I use the box as a dummy object, just to test):
val configuration = LocalConfiguration.current
val resources = LocalContext.current.resources
Box(
modifier = Modifier
.fillMaxWidth()
.height(0.2.dw)
.background(Color.Red)
.clickable {
// to change the language
val locale = Locale("bg")
configuration.setLocale(locale)
resources.updateConfiguration(configuration, resources.displayMetrics)
viewModel.updateLanguage()
}
) {
}
Then it switches the language value using the updateLanguage()
method
@HiltViewModel
class CityWeatherViewModel @Inject constructor(
private val getCityWeather: GetCityWeather
) : ViewModel() {
private val _languageSwitch = mutableStateOf(true)
var languageSwitch: State<Boolean> = _languageSwitch
fun updateLanguage() {
_languageSwitch.value = !_languageSwitch.value
}
}
The problem is that in order to update each Text
composable, I need to pass the viewmodel
to all descendant that use Text
and then use some bad logic to force update each time, some changes in the view model occur.
@Composable
fun SomeChildDeepInTheHierarchy(viewModel: CityWeatherViewModel, @StringRes textResId: Int) {
Text(
text = stringResource(id = if (viewModel.languageSwitch.value) textResId else textResId),
color = Color.White,
fontSize = 2.sp,
fontWeight = FontWeight.Light,
fontFamily = RobotoFont
)
}
It works, but that is some really BAD logic, and the code is very ugly! Is there a standard way of changing the Locale
using Jetpack Compose dynamically?