Version Name

dynamic-theme-colors

Convenience library aimed to blend your app theme colors with Material 3 dynamic colors system using Jetpack Compose for Android 12+.

How can i use it?

Just add this to your settings.gradle:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}

Then, in your build.gradle:

	dependencies {
		implementation 'com.github.ygorluizfrazao:dynamic-theme-colors:v1.0.0-buildtest01'
	}

Why it exists?

In materialv3 we have the dynamic color system, which, in Android, by default, ignores your defined theme colors and only uses the system colors, when creating your theming composable. This lib just blends your defined theme colors with the system colors.

How to use it?

The main way to use it is to call the function:

fun ColorScheme.blendWithSystemUI(
    darkTheme: Boolean = isSystemInDarkTheme(),
    blendRatio: Float = .5f
): ColorScheme
  • darkTheme -> Decides which system theme to blend with, Light or Dark;
  • blendRatio -> How much system theme colors will contribute to the final ColorScheme;

Example:

The following device has a Greenish/Cyanish theme…

with 0 blend ration with 0.3 blend ration with 0.6 blend ration with 0.6 blend ration
  • blendRatio = 0:

with 0 blend ration

  • blendRatio = 0.3:

with 0.3 blend ration

  • blendRatio = 0.6:

with 0.6 blend ration

  • blendRatio = 0.95:

with 0.6 blend ration

this demo is available in the source files of this repos.

the code would be like:

//Theme.kt

@Composable
fun DynamicThemeColorsTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    baseColorScheme: ColorScheme,
    blendRatio: Float = .5f,
    content: @Composable () -> Unit
) {
    
    val dynamicColorScheme =
        baseColorScheme.blendWithSystemUI(darkTheme = darkTheme, blendRatio)

    val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as Activity).window
            window.statusBarColor = dynamicColorScheme.primary.toArgb()
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
        }
    }

    MaterialTheme(
        colorScheme = dynamicColorScheme,
        typography = Typography,
        content = content
    )
}

//MainActivity.kt

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalFoundationApi::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            var blendRatio by rememberSaveable {
                mutableStateOf(0f)
            }
            val colorScheme by remember {
                mutableStateOf(randomColorScheme())
            }

            DynamicThemeColorsTheme(blendRatio = blendRatio, baseColorScheme = colorScheme) {
                val listOfColors = MaterialTheme.colorScheme.toPairList()
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = Color.White
                ) {
                    Column(modifier = Modifier.fillMaxSize()) {
                        Slider(value = blendRatio, onValueChange = {
                            blendRatio = it
                        })
                        Text(
                            modifier = Modifier
                                .fillMaxWidth()
                                .background(Color.Black)
                                .padding(horizontal = 8.dp, vertical = 4.dp),
                            color = Color.White,
                            text = "blendRatio: ${String.format("%.2f",blendRatio)}",
                            fontWeight = FontWeight.Bold,
                            textAlign = TextAlign.Center,
                            fontSize = 12.sp
                        )
                        LazyVerticalStaggeredGrid(
                            modifier = Modifier
                                .fillMaxSize()
                                .padding(vertical = 8.dp, horizontal = 16.dp),
                            horizontalArrangement = Arrangement.spacedBy(8.dp),
                            verticalItemSpacing = 8.dp,
                            columns = StaggeredGridCells.Adaptive(150.dp)
                        ) {
                            items(
                                items = listOfColors,
                                key = {
                                    it.first
                                }
                            ) {
                                Card(modifier = Modifier.height(100.dp)) {
                                    Box(
                                        modifier = Modifier
                                            .fillMaxSize()
                                            .background(it.second)
                                    ) {
                                        Text(
                                            modifier = Modifier
                                                .fillMaxWidth()
                                                .background(Color.Black)
                                                .padding(horizontal = 8.dp, vertical = 4.dp),
                                            color = Color.White,
                                            text = it.first,
                                            fontWeight = FontWeight.Bold,
                                            textAlign = TextAlign.Center,
                                            fontSize = 12.sp
                                        )
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Other resources

This lib also has some extensions for ColorSchemeclass, as listed:

  • fun randomARGBColor(...) -> Creates a random color;
  • fun randomColorScheme(...) -> Creates a scheme with random colors as default, if you want some specific color, pass as a param.
  • fun ColorScheme.blend(anotherColorScheme: ColorScheme, ratio: Float = 0.5f): ColorScheme -> Blends two ColorScheme objects.
  • fun ColorScheme.maskedBy(mask: ColorScheme, maskOpacity: Float): ColorScheme -> masks a ColorScheme using another after applying the maskOpacity, the alpha sum will be 1.
  • fun ColorScheme.withAlpha(alpha: Float): ColorScheme -> Adds the desired transparency to the ColorScheme object.

Hope it helps you.

GitHub

View Github