Question about MaterialTheme and overriding a colo...
# compose
b
Question about MaterialTheme and overriding a color in a segment of code. If i had a layout
Copy code
Column
  Button1
  *OddUi*
  Button3
Lets say i wanted to override
primary
and
onPrimary
when rendering the OddUi content. What’s the best way of doing this? MaterialTheme’s colors are
mutableStateOf
, so do i write
Copy code
Button1()
MaterialTheme.primary = somethingElse
MaterialTheme.Colors.onPrimary = somethingElse
OddUi()
// restore the two colors
Button2
This feels odd or would i write
Copy code
Button1()
CompositionLocalProvider(LocalColors provides MaterialTheme.colors.copy(primary = ..., onPrimary = ...) {
   OddUi()
}
Button2
With this though, localColors is internal, so i can’t override it, right? Is there a third option?
c
CompositionLocal is one way. What is happening in that code is that you are providing a different set of colors to LocalColors
The other alternative is you wrap OddUi in another MaterialTheme or YourAppTheme block and override:
Copy code
MaterialTheme(
    colors = MaterialTheme.colors.copy(primary = ...)
) {
    OddUi()
}
If your overrides grow beyond two values, I may recommend creating a separate theme Composable that wraps MaterialTheme or YourAppTheme, then use that directly in the OddUi hierarchy
Copy code
@Composable
fun OddUi() {
    OddUiTheme {
        ...
    }
}

@Composable
private fun OddUiTheme(
    content: @Composable () -> Unit
) {
    MaterialTheme(
        colors = ...,
        typography = ...,
        ...,
    ) {
        content()
    }
}
b
Got it, thanks!
Also, do you know what the intent is of having the properties of
Colors
be mutableStates? Rather than having the
Colors
class be immutable?
c
I didn’t design the API but my guess is that it’s to support switching colors on the fly based on app / system state, to then recompose hierarchies, e.g. switching between light/dark mode. @Louis Pullen-Freilich [G] could maybe provide more details.
l
For this case you can just use another
MaterialTheme
with a different set of colors around the content as Chris mentioned.
MutableState
is used so that if you are animating / changing one color, only components that consume that color recompose, which makes it a lot more efficient to animate colors in a theme
🙏 1
1
👏 1
r
I had been wondering why the colors were
MutableState
and in fact still am. In Material 3 terms, in ColorScheme.kt, functions
lightColorScheme
and
darkColorScheme
return a new
ColorScheme
. Under what conditions are the individual colors then changed within those `ColorScheme`s?
l
Internally
MaterialTheme
uses the color schemes provided to update its internal color scheme, by changing each individual color https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]nMain/kotlin/androidx/compose/material3/MaterialTheme.kt;l=66
r
Thanks. I've added extended colors into my app, modeling my
ExtendedColorScheme
class on
ColorScheme
. I made my colors
mutableStateOf
as well with a TBD to understand why. Now I think that I don't need to make them mutable 🙂.
same 1
l
If you have no plans to animate between different color schemes, or you don’t regularly change some values in your scheme (for example, changing just the primary color depending on some content on the screen like in a music player application) then yeah, there’s no need to make them mutable. It can just be a
CompositionLocal
 with a simple class of immutable colors