Reputation: 1363
I'm new to Jetpack Compose, so I'm struggling to implement a feature which is dynamic colors (and font, size,... but I think they are the same so I'll just focus on color) at run time from backend. I'll let the app the some default colors, and a whole default splash screen just to load the colors setting from the backend. In case the API request failed, it would use the last succeeded requested colors or just the default color.
Tutorials I found round the internet was just about changing the dark/light theme at run time, not changing a specific color in the color pack. In those tutorials, the color is defined in Colors.kt
file which is not a composable or class or object, ...
I imagine the color within lightColors
or darkColors
would be something like this.
return lightColors(
primary = Color(android.graphics.Color.parseColor("#" + dynamicColorMap["One"])),
...
}
And when dynamicColorMap
changes in the splashscreen, all screen later will have reference to the new value, but I don't know how to update its variable outside of a composable.
I thought of using DB to store the colors, but getting the data from DB is async, so it cannot be query in the default Colors.kt
like var colorOne = DBManager.getColor("One")
, I can run the async task in my splash screen before changing to the next screen but then the problem again is how to have a global state that my theme composable wrapper can have access to on every screen?
I just don't know where to start for these case.
Thank you for your time
EDIT: I currently having the project structured in MVVM. For now, only one activity (MainActivity) is present, and inside that activity, the splash screen component or home screen or login screen,... are being navigated. So is it a good practice to create a viewmodel for the mainactivity screen, that can holds the color state for the theme?
Upvotes: 1
Views: 2287
Reputation: 1363
Thanks @Maciej Ciemiega for the suggestion. I ended up structure my code like that.
In my MainActivity.kt
I create a viewmodel for it.
val mainActivityViewModel by viewModels<MainActivityViewModel>()
MyTheme(mainActivityViewModel = mainActivityViewModel) {
initNavigationController(navController)
Surface(color = MaterialTheme.colors.background) {
if (mainActivityViewModel.appSettingsState.value.appSettings.colorsMapLight.size != 0
&& mainActivityViewModel.appSettingsState.value.appSettings.colorsMapDark.size != 0) {
navController.navigate(NavigationDestinations.homeScreen)
}
}
}
my initNavigationController
function shows the splashscreen first. But it doesn't do anything. The getting app settings configuration is called in MyTheme
composable via the mainActivityViewModel
, and MyTheme
will use the state from the viewmodel to define the theme, and the navController.navigate
is based on the state as you guys can see in the if
above.
I don't know if this is a good practice or not, or when my app grows it would be a mess or not, but at least it works for me. I tried with font styles too and it works like a charm.
Upvotes: 1