What’s Dynamic Theme
Dynamic Theme is a Material Design-based Theme Management System for Android Jetpack Compose. Up until now, changing the theme on Android has been a very difficult task. Dynamic Theme was created to make Android’s theme management easy. Theming can be applied by simply adding ‘ProvidesTheme’ to the top-level declaration in Jetpack Compose.
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { DynamicThemeService.getInstance(applicationContext).ProvidesTheme { // Add Compose Functions } } } }
Since this theme management system is based on Material2, knowledge of the Material2 Color System is required to use this library.
Preview
Downloads
Maven Central
Getting Started
Add the mavenCentral() on project level(root level) build.gradle file:
allprojects { repositories { mavenCentral() } }
Add dependency on module level build.gradle file:
build.gradle
dependencies { implementation "io.github.seyoungcho2:dynamic-theme-compose:0.0.1" }
If using build.gradle.kts
build.gradle.kts
dependencies { implementation("io.github.seyoungcho2:dynamic-theme-compose:0.0.1") }
Features
Table of Contents
ThemeModelKey
The ThemeModelKey is used to register the ThemeModel and access the registered ThemeModel.
- ThemeModelKey can be declared by using the function on ThemeModelKey
val THEME_MODEL_KEY_BLUE = ThemeModelKey.of("Blue")
- ThemeModelKey.Default is predefined for the default theme. If the current theme is not set, then ThemeModelKey.Default is used to retrieve the ThemeModel. Alternatively, you can also access the default ThemeModel using it.
DynamicThemeService.getInstance(context).getThemeModel(ThemeModelKey.Default)
ThemeModel
The ThemeModel is a data class for saving themes. It contains three parameters:
- ColorPalette: Color combinations for the theme.
- Typography: Configurations of typography for the theme.
- Shapes: Shape configurations for the theme.”
data class ThemeModel( val colorPalette: ColorPalette = ColorPalette(), val typography: Typography = Typography(), val shapes: Shapes = Shapes() )
I will briefly explain these three parameters in the following sections. However, you don’t need to define all of them. You only need to set up the specific parts you want to customize, as shown below.
val THEME_MODEL_KEY_BLUE = ThemeModelKey.of("Blue") private val THEME_MODEL_BLUE = ThemeModel( colorPalette = ColorPalette( lightModeColors = ColorPalettes.BlueColorPalette, darkModeColors = ColorPalettes.BlueColorPalette, ) )
ColorPalette
The ColorPalette contains two parameters: ‘lightModeColors’ for the Light Theme and ‘darkModeColors’ for the Dark Theme. When the device is set to dark mode on system, the darkModeColors are automatically used.
data class ColorPalette(
val lightModeColors: Colors = LightModeColorPalette,
val darkModeColors: Colors = DarkModeColorPalette
)
Colors class is Material2 class which consist of primary, primaryVariant, secondary, secondaryVariant, background, surface, error, onPrimary, onSecondary, onBackground, onSurface, onError, isLight variables. You can find more about color system on Material2 Color System, Material2 Color Document
Typography
Typography contains design data for characters. This is also part of Material2 Typography System. You will probably see familiar things like h1, h2, h3, subtitle1, subtitle2, body1, body2. Which are used to build heirarchy of characters. See Material2 Typography
Shapes
See Material2 Shapes document
How to use DynamicThemeService
DynamicThemeService is initialized as a singleton object by using DynamicThemeService.getInstance(applicationContext). it has following responsibilities:
- Register Themes
- Get Registered Themes
- Set Current Theme
- Get Current Theme
- Provide Theme Composable with Current Theme
- Provide Theme Composable with ThemeModel
Register Themes
Registering both single and multiple theme supported. Default theme can also be changed.
Single Theme Registration
DynamicThemeService.getInstance(applicationContext).apply { registerThemeModel( ThemeModelKey.of("Pink"), ThemeModel( colorPalette = ColorPalette( lightModeColors = ColorPalettes.PinkColorPalette, darkModeColors = ColorPalettes.PinkColorPalette, ), shapes = Shapes.DEFAULT_ROUNDED_SHAPE ) ) registerThemeModel( ThemeModelKey.of("Blue"), ThemeModel( colorPalette = ColorPalette( lightModeColors = ColorPalettes.BlueColorPalette, darkModeColors = ColorPalettes.BlueColorPalette, ) ) ) }
Multiple Theme Registration
DynamicThemeService.getInstance(applicationContext).apply { registerThemeModels(ThemeModels.getSupportedThemeModels()) } fun getSupportedThemeModels(): Map<ThemeModelKey, ThemeModel> = mapOf( THEME_MODEL_KEY_DEFAULT to THEME_MODEL_DEFAULT, THEME_MODEL_KEY_BLACK to THEME_MODEL_BLACK, THEME_MODEL_KEY_PINK to THEME_MODEL_PINK, THEME_MODEL_KEY_BLUE to THEME_MODEL_BLUE, THEME_MODEL_KEY_WHITE to THEME_MODEL_WHITE )
Register Default Theme
DynamicThemeService.getInstance(applicationContext).apply { registerThemeModel( ThemeModelKey.Default, ThemeModel( colorPalette = ColorPalette( lightModeColors = ColorPalettes.BlueColorPalette, darkModeColors = ColorPalettes.BlueColorPalette, ) ) ) }
Get Registered Themes
Get Single Registered Theme
DynamicThemeService.getInstance(applicationContext).getThemeModel(themeModelKey)
Get All Registered Themes
val registeredThemes: Map<ThemeModelKey, ThemeModel> = DynamicThemeService.getInstance(applicationContext).getRegisteredThemes()
Set Current Theme
suspend fun setCurrentTheme(themeModelKey: ThemeModelKey){ DynamicThemeService.getInstance(applicationContext).setCurrentTheme(themeModelKey) }
Get Current Theme
Get Current Theme
val currentThemeModel: ThemeModel = async { DynamicThemeService.getInstance(applicationContext).getCurrentThemeModel() }.await()
Get Current Theme with Reactively with Flow
val currentThemeModelFlow: Flow<ThemeModel> = DynamicThemeService.getInstance(applicationContext).currentThemeModel
Provide Current Theme Composable
DynamicThemeService.getInstance(applicationContext).ProvidesTheme { // Write Composable Functions }
Provide Theme Composable with ThemeModel
DynamicThemeService.getInstance(applicationContext).ProvidesTheme(themeModel) { // Write Composable Functions }
Find this repository useful?👍
Support it by making star⭐! You can see stargazers here. Also, follow me on GitHub for further updates
License
Designed and developed by 2023 seyoungcho2 (Seyoung Cho) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.