IllegalStateException: CompositionLocal LocalConfiguration not present Android - android

I'm trying to use staticCompositionLocalOf in Jetpack Compose according to this article on Medium.
This is my ProvidableCompositionLocal
val lightColors = lightColors(
primary = LightColor.BackgroundWhite,
primaryVariant = LightColor.ToolbarWhite,
secondary = LightColor.FabBlue,
secondaryVariant = LightColor.BackgroundWhite,
surface = LightColor.SurfaceWhite,
onPrimary = LightColor.TextBlack,
onSecondary = LightColor.TextBlack,
onSurface = LightColor.TextBlack
)
val darkColors = darkColors(
primary = DarkColor.BackgroundBlue,
primaryVariant = DarkColor.ToolbarBlue,
secondary = DarkColor.FabGrey,
secondaryVariant = DarkColor.BackgroundBlue,
surface = DarkColor.SurfaceBlue,
onPrimary = Color.White,
onSecondary = Color.White,
onSurface = Color.White
)
private val DarkColorPalette =
Colors(
material = darkColors,
toolbar = DarkColor.ToolbarBlue,
background = DarkColor.BackgroundBlue,
surface = DarkColor.SurfaceBlue,
fab = DarkColor.FabGrey,
pink = DarkColor.Pink
)
private val LightColorPalette =
Colors(
material = lightColors,
toolbar = LightColor.ToolbarWhite,
background = LightColor.BackgroundWhite,
surface = LightColor.SurfaceWhite,
fab = LightColor.FabBlue,
pink = LightColor.Pink
)
val TheColor: Colors
#Composable
#ReadOnlyComposable
get() = LocalColors.current
}
val LocalColors = staticCompositionLocalOf { DarkColorPalette }
This is the wrapper around the normal Colors class provided by Compose class. The material variable is the normal Colors class.
data class Colors(
val material: Colors,
val toolbar: Color,
val background: Color,
val surface: Color,
val fab: Color,
val pink: Color
) {
val primary: Color get() = material.primary
val primaryVariant: Color get() = material.primaryVariant
val secondary: Color get() = material.secondary
val secondaryVariant: Color get() = material.secondaryVariant
// val background: Color get() = material.background
// val surface: Color get() = material.surface
val error: Color get() = material.error
val onPrimary: Color get() = material.onPrimary
val onSecondary: Color get() = material.onSecondary
val onBackground: Color get() = material.onBackground
val onSurface: Color get() = material.onSurface
val onError: Color get() = material.onError
val isLight: Boolean get() = material.isLight
}
I have also provided it in my Theme function as shown below. I'm getting the darkTheme from Android DataStore
#Composable
fun BMICalculatorTheme(
darkTheme: Boolean,
content: #Composable () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
CompositionLocalProvider(LocalColors provides colors) {
MaterialTheme(
colors = colors.material,
typography = CabinTypography,
shapes = Shapes,
content = content
)
}
}
However, I'm getting the below error but can't find any online resources that can help me fix it. In case any further information is needed, I would be more than happy to clarify. Any help would be highly appreciated.
IllegalStateException: CompositionLocal LocalConfiguration not present
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.noLocalProvidedFor(AndroidCompositionLocals.android.kt:123)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.access$noLocalProvidedFor(AndroidCompositionLocals.android.kt:1)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$LocalConfiguration$1.invoke(AndroidCompositionLocals.android.kt:44)
at androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$LocalConfiguration$1.invoke(AndroidCompositionLocals.android.kt:43)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at androidx.compose.runtime.LazyValueHolder.getCurrent(ValueHolders.kt:29)
at androidx.compose.runtime.LazyValueHolder.getValue(ValueHolders.kt:31)
at androidx.compose.runtime.ComposerImpl.resolveCompositionLocal(Composer.kt:1895)
at androidx.compose.runtime.ComposerImpl.consume(Composer.kt:1865)
at androidx.compose.foundation.DarkTheme_androidKt.isSystemInDarkTheme(DarkTheme.android.kt:52)
at com.octagon_technologies.bmicalculator.data.ThemeDataStore$isDarkMode$$inlined$map$1$2.emit(Collect.kt:135)
at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catchImpl$$inlined$collect$1.emit(Collect.kt:134)
at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(Unknown Source:4)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:77)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:59)
at androidx.datastore.core.SingleProcessDataStore$data$1$invokeSuspend$$inlined$map$1$2.emit(Collect.kt:139)
at kotlinx.coroutines.flow.FlowKt__LimitKt$dropWhile$$inlined$unsafeFlow$1$lambda$1.emit(Collect.kt:137)
at kotlinx.coroutines.flow.StateFlowImpl.collect(StateFlow.kt:348)
at kotlinx.coroutines.flow.StateFlowImpl$collect$1.invokeSuspend(Unknown Source:12)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.android.kt:57)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)

The problem appears to be here:
... ThemeDataStore$isDarkMode$$inlined$map$1$2.emit(Collect.kt:135)
From the stack trace it looks like the isSystemInDarkTheme is being called inside a lambda passed to collect() which, since it is an #Composable function, it should only be called from another #Composable function and cannot be called inside a flow collect().
The compiler should have reported this an error. Please consider reporting this as a compose compiler plugin bug.

Related

Accompanist systemUiController darkIcons doesn't work on Android 11

I'm using the Accompanist systemUiController library and I'm setting
darkIcons=false
while in Light Theme but the effect doesn't apply on devices with android 11. It seems to work on devices with android 10 for example.
This is the code with which I'm trying to set the colors.
val systemUiController = rememberSystemUiController()
systemUiController.setStatusBarColor(color=statusBarColor,darkIcons=false)
where statusBarColor is a darker color which represents the reason I want white foreground/icons
While in Dark Theme it works to set darkIcons
to both true and false and the effect applies accordingly
This is the status bar on LightTheme with darkIcons=false and darkIcons=true
This is the status bar on DarkTheme with darkIcons=false
This is the status bar on DarkTheme with darkIcons=true
For reference this is my whole Theme.kt
private val LightBase = ASBTheme(
material = lightColors(
background = FigmaPrimaryWhite,
onBackground = FigmaTextBlack,
surface = FigmaPrimaryWhite,
onSurface = FigmaTextBlack,
primary = FigmaSecondaryAvastBlue,
error = FigmaStatusPink,
),
textColorLabel = FigmaSecondaryAvastPurple,
colorAccent = FigmaPrimaryGreen,
... //bunch of custom colors
)
private val DarkBase = ASBTheme(
material = darkColors(
background = FigmaPrimaryBlackBg,
onBackground = FigmaTextWhite,
surface = FigmaSecondaryAvastBlueDark,
onSurface = FigmaTextWhite,
primary = FigmaSecondaryBlackDark,
error = FigmaStatusPink
),
textColorLabel = FigmaSecondaryAvastPurpleBright,
colorAccent = FigmaStatusGreen,
... //bunch of custom colors
)
private val LocalAsbTheme = staticCompositionLocalOf { LightBase }
var navBarColor: Color? = null
var statusBarColor: Color? = null
#Composable
fun ASBTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: #Composable () -> Unit
) {
val colors = if (darkTheme) {
DarkBase
} else {
LightBase
}
if (darkTheme) {
navBarColor = DarkBase.background
statusBarColor = DarkBase.primary
} else {
navBarColor = LightBase.background
statusBarColor = LightBase.primary
}
SetBarsTheme(statusBarColor!!, navBarColor!!)
CompositionLocalProvider(
LocalAsbTheme provides colors,
) {
MaterialTheme(
colors = colors.material,
content = content,
)
}
}
val MaterialTheme.asbTheme: ASBTheme
#Composable
#ReadOnlyComposable
get() = LocalAsbTheme.current
SetBarsTheme() is where I'm trying to set the status bar colors depending on the lifecycle event so that the colors would maintain after onPause() / onStop(). I also tried to set the colors outside of this logic and the bug still persists.
#Composable
fun SetBarsTheme(
statusBarColor: Color,
navigationBarColor: Color,
darkIcons:Boolean=false,
) {
val lifecycleOwner = LocalLifecycleOwner.current
val systemUiController = rememberSystemUiController()
DisposableEffect(lifecycleOwner) {
// Create an observer that triggers our remembered callbacks
// for sending analytics events
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME) {
systemUiController.setStatusBarColor(color=statusBarColor,darkIcons)
systemUiController.setNavigationBarColor(color=navigationBarColor)
}
}
// Add the observer to the lifecycle
lifecycleOwner.lifecycle.addObserver(observer)
// When the effect leaves the Composition, remove the observer
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
}
There's a fixed bug, make sure you're using the latest Accompanist version.
If you still able to reproduce it, you should report it, including used device/dependencies versions.

Compose - Custom MaterialTheme colors not working?

I want to custom colors system using Compose, but it isn't working. It effected by colors in themes.xml.
Activity
class DemoComposeMainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val colorPrimary = colorResource(R.color.md_green_500)
val colorSecondary = colorResource(R.color.md_orange_500)
val colors = lightColors(
primary = colorPrimary,
primaryVariant = colorPrimary,
onPrimary = Color.White,
secondary = colorSecondary,
secondaryVariant = colorSecondary,
onSecondary = Color.White)
MaterialTheme(colors = colors) {
// TODO
}
}
}
}
Please help me. Thanks.
The statusbar color is based on the android:statusBarColor defined in your app theme.
If you want to change the statusBar color you can use the accompanist library.
Something like.
val systemUiController = rememberSystemUiController()
val useDarkIcons = MaterialTheme.colors.isLight
SideEffect {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
darkIcons = useDarkIcons
)
// setStatusBarsColor() and setNavigationBarsColor() also exist
}

How to add extra colors into MaterialTheme in Android Jetpack Compose?

Android Jetpack Compose Colors class contains a set of color types a material themed app can be implemented with. In case my app theme requires some extra color types, how can I add these extra colors so they would be available via MaterialTheme object?
Just a small change to Valeriy Katkov's answer
In some versions of the android studio, the following code will not work
#Composable
val Colors.myExtraColor: Color
get() = if (isLight) Color.Red else Color.Green
#Composable
fun ExtraColorExample() {
Text(
text = "test",
color = MaterialTheme.colors.myExtraColor // <-- the newly added color
)
}
It will show an error
This annotation is not applicable to target 'top-level property
without backing field or delegate'
To fix this either write it like this
#get:Composable
val Colors.myExtraColor: Color
get() = if (isLight) Color.Red else Color.Green
Or
val Colors.myExtraColor: Color
#Composable
get() = if (isLight) Color.Red else Color.Green
The version I found this error in
Android Studio Arctic Fox | 2020.3.1 Canary 12
Build #AI-203.7148.57.2031.7226969, built on March 23, 2021
Runtime version: 11.0.8+10-b944.6842174 amd64
VM: OpenJDK 64-Bit Server VM by N/A
Windows 10 10.0
There are basically two approaches to this:
The naive way is to just create extension properties tot hard-code the colors. If you don't want to support multiple themes or light/dark mode this works just fine.
If you want to integrate your colors properly to the theme, you can read my article on it, as it's a bit long to inline here: https://gustav-karlsson.medium.com/extending-the-jetpack-compose-material-theme-with-more-colors-e1b849390d50
But in short, the steps are:
Create your own MyColors class that holds a reference to Colors as well as your new colors.
Create a CompositionLocal that holds a MyColor instance.
Create your theme and wrap the MaterialTheme in a CompositionLocalProvider where the CompositionLocal provides MyColors. Make sure to also assign the Colors instance from MyColors to the MaterialTheme.
Create an extension property on MaterialTheme that refers to the CompositionLocal holding MyColors. This is how you refer to your new colors.
This will allow you to introduce new colors to the theme that will update dynamically as the theme changes.
Extending Colors class
You can easily add an extension property to the Colors class so it would be available via any Colors object across your app.
#Composable
val Colors.myExtraColor: Color
get() = if (isLight) Color.Red else Color.Green
#Composable
fun ExtraColorExample() {
Text(
text = "test",
color = MaterialTheme.colors.myExtraColor // <-- the newly added color
)
}
There's an example in the compose documentation as well, see Extending Material colors.
Specifying a content alpha
In case the color you're missing differs from an existing one only by it's alpha and the purpose of the color is to change a content priority, there's no need to add an additional color to the theme. You can specify a content alpha for a hierarchy by providing a value for LocalContentAlpha.
CompositionLocalProvider(
LocalContentAlpha provides ContentAlpha.medium,
LocalContentColor provides MaterialTheme.colors.onSurface
) {
// this text is displayed using ContentAlpha.medium
// and MaterialTheme.colors.onSurface color
Text("Hello world!")
}
See Content Alpha documentation for more details. There's also Content Alpha section in Jetpack Compose Theming codelab.
For Material3, I had to extend the androidx.compose.material3.ColorScheme object, since MaterialTheme.colors does not exist.
val ColorScheme.successContainer: Color #Composable
get() = if (!isSystemInDarkTheme()) Color(0xFFd6ffe0) else Color(0xFF269300)
Text(
text = "Hello World",
modifier = Modifier.background(color = MaterialTheme.colorScheme.successContainer)
)
"CompositionLocal" answer is right, but maybe not quite easy to understand.
Android Developers on youtube send a video: "Compose by example".
https://www.youtube.com/watch?v=DDd6IOlH3io
on 6:28/22:07 Introduced this usage.
Here is my sample code to learn this part, for someone to copy:
Define the theme:
val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)
val yellow200 = Color(0xffffeb46)
val yellow400 = Color(0xffffc000)
val yellow500 = Color(0xffffde03)
val yellowDarkPrimary = Color(0xff242316)
val yellowLightPrimary = Color(0xffd4d3f6)
class RabbitColorPalette(
val raFirstColor: Color,
val raSecColor: Color,
val raOnFirstColor: Color,
val raOnSecColor: Color
)
val rabbitPurple = RabbitColorPalette(Purple200,Purple500,Purple700,Teal200)
val rabbitYellow = RabbitColorPalette(yellow200,yellow400,yellow500,yellowDarkPrimary)
val rabbitColors = compositionLocalOf<RabbitColorPalette>{
rabbitPurple
}
#Composable
fun RabbitThemePink(
content: #Composable() () -> Unit
) {
val colors = rabbitPurple
CompositionLocalProvider(rabbitColors provides colors){
MaterialTheme(
typography = Typography,
shapes = Shapes,
content = content
)
}
}
object RabbitTheme{
val colors: RabbitColorPalette
#Composable get() = rabbitColors.current
}
#Composable
fun RabbitThemeYellow(
content: #Composable() () -> Unit
) {
val colors = rabbitYellow
CompositionLocalProvider(rabbitColors provides colors){
MaterialTheme(
typography = Typography,
shapes = Shapes,
content = content
)
}
}
usage
class RabbitThemeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
RabbitThemePink {
SampleLayout()
}
}
}
#Composable
fun SampleLayout() {
Column {
Text(text = "sample", modifier = Modifier.background(color = RabbitTheme.colors.raFirstColor))
Text(text = "des", modifier = Modifier.background(color = RabbitTheme.colors.raSecColor))
}
}
#Preview
#Composable
fun ConstraintLayoutContentPinkPreview() {
RabbitThemePink {
SampleLayout()
}
}
#Preview
#Composable
fun ConstraintLayoutContentYellowPreview() {
RabbitThemeYellow {
SampleLayout()
}
}
}
In my case, the theme component gets its parameters from the saved settings, i.e. The app theme is independent of the device theme. For this reason, the current answers don't work for me.
My implementation is relevant for Material 3 and directly depends on the passed parameters.
Color.kt
package com.my.app.theme
import androidx.compose.ui.graphics.Color
val SuccessLightColor = Color(0xFF436915)
val SuccessLightContainerColor = Color(0xFFC2F18D)
val SuccessDarkColor = Color(0xFFA7D474)
val SuccessDarkContainerColor = Color(0xFF2D5000)
Theme.kt
package com.my.app.theme
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme()
private val LightColorScheme = lightColorScheme()
var successColorSchemeColor by mutableStateOf(SuccessLightColor)
var successContainerColorSchemeColor by mutableStateOf(SuccessLightColor)
#Suppress("unused")
var ColorScheme.success: Color
get() = successColorSchemeColor
set(value) {
successColorSchemeColor = value
}
#Suppress("unused")
var ColorScheme.successContainer: Color
get() = successContainerColorSchemeColor
set(value) {
successContainerColorSchemeColor = value
}
#Composable
fun Theme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: #Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
colorScheme.success = if (darkTheme) {
SuccessDarkColor
} else {
SuccessLightColor
}
colorScheme.successContainer = if (darkTheme) {
SuccessDarkContainerColor
} else {
SuccessLightContainerColor
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
Use case:
Box(
modifier = Modifier
.size(128.dp)
.background(
color = MaterialTheme.colorScheme.successContainer
)
)

How do I use Color resource directly in Jetpack Compose?

I want to use custom colors defined in the colors.xml class directly without using the Material theme colors or the default theme provided by the Jetpack. Is there any straightforward way to do it?
You can use colorResource() which loads a color resource.
Text(
text = "Hello World",
color = colorResource(R.color.purple_200)
)
To use color in jetpack compose using recommended create a package ui.theme in com.<domain_name>.<app_name> which will likely be present by default if you are creating empty compose project. Now create Color.kt and Theme.kt kotlin files if they are not present in your project.
In Color.kt add the colors you need
package com.<domain_name>.<app_name>.ui.theme
import androidx.compose.ui.graphics.Color
val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)
val Flower = Color(0xFF4CAF50)
val Deer = Color(0xFFFF5722)
val Mango = Color(0xFFFF9800)
val AppbarColor = Color(0xFF2196F3)
Here is ready to use a Material Color template made by me
There are 3 common ways of using colors
Method 1 : Directly use color
import com.<domain_name>.<app_name>.ui.theme.*
Text(text = "Hello ", color = Flower)
Method 2 : Override default MaterialTheme colors
Now in, Theme.kt
private val DarkColorPalette = darkColors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200,
onBackground = Flower //Custom color
)
private val LightColorPalette = lightColors(
primary = Purple500,
primaryVariant = Purple700,
secondary = Teal200,
onBackground = Deer //Custom color
/* Other default colors to override
background = Color.White,
surface = Color.White,
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black,
*/
)
#Composable
fun NotepadTheme(darkTheme: Boolean = isSystemInDarkTheme(),
content:#Composable() () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
MainActivity.kt
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ColorApp()
}
}
}
#Composable
fun ColorApp() {
ColorTheme {
Surface(modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
#Composable
fun Greeting(name: String) {
Text(text = "Hello $name!", color = MaterialTheme.colors.onBackground) //Using color
}
#Preview(
showBackground = true, name = "Light mode",
uiMode = Configuration.UI_MODE_NIGHT_NO or
Configuration.UI_MODE_TYPE_NORMAL
)
#Preview(
showBackground = true, name = "Night mode",
uiMode = Configuration.UI_MODE_NIGHT_YES or
Configuration.UI_MODE_TYPE_NORMAL
)
#Composable
fun DefaultPreview() {
ColorApp()
}
Method 3 : Custom theme (Recommended method)
Text(text = "Hello ", color = AppNameTheme.colors.customColor)

How to reference theme attributes in Jetpack Compose?

So in the current andriod development, if we need to reference to a color set in the theme, we could simply do: (in layout xml)
....
<TextView
...
android:textColor="?attr/colorPrimary"
.../>
....
If I set a color blue in the theme. I will get that color in the textview above.
I was wondering how I could do the same in Jetpack Compose. In Compose, we do,
MaterialTheme(...) {
Column {
Text(
...
textStyle = TextStyle(color = ????) // How to I reference to the theme?
)
}
}
You can use something like:
Text(text = "....",
style = TextStyle(color = MaterialTheme.colors.primary))
Compose provide ColorPalette based on Material color specification to generate you app theme. It provide lightColorPalette and darkColorPalette for defining theme for light and dark mode respectively.
val lightThemeColors = lightColorPalette(
primary = Color(0xFFFFFFFF),
primaryVariant = Color(0xFFFFFFFF),
onPrimary = Color.Black,
secondary = Color.Transparent,
onSecondary = Color.White,
background = Color.White,
onBackground = Color(0xFF212121),
surface = Color.White,
onSurface = Color(0xFF212121),
error = Color.Red,
onError = Color.White
)
val darkThemeColors = darkColorPalette(
primary = Color(0xFF000000),
primaryVariant = Color(0xFF000000),
onPrimary = Color.White,
secondary = Color.White,
onSecondary = Color.White,
surface = Color(0xFF212121),
background = Color(0xFF212121),
onBackground = Color.White,
onSurface = Color.White,
error = Color.Red,
onError = Color.White
)
MaterialTheme(
colors = if(isSystemInDarkTheme()) darkThemeColors else lightThemeColors
) {
Column {
Text(
textStyle = TextStyle(color = MaterialTheme.colors.primary)
)
}
}
If you want to add more custom color to you theme you can use ColorPalette with extension variable like shown below
#Composable
val ColorPalette.myColor: Color
get() = if(!isLight) Color(0xFF424242) else Color.White
Now you can use MaterialTheme.colors.myColor to include.
If you want to include color from android colors xml you can do that using colorResource(id = R.color.anyName) function.
You can try this:
inline fun <T> Resources.Theme.getAttribute(
#AttrRes attr: Int,
block: (TypedArray) -> T,
): T {
val a = obtainStyledAttributes(intArrayOf(attr))
return block(a).also { a.recycle() }
}
fun Resources.Theme.getDrawableAttribute(#AttrRes attr: Int): Drawable =
getAttribute(attr) { it.getDrawable(0)!! }
fun Resources.Theme.getDimensionAttribute(#AttrRes attr: Int, defaultValue: Float = 0f): Float =
getAttribute(attr) { it.getDimension(0, defaultValue) }
fun Resources.Theme.getStringAttribute(#AttrRes attr: Int): String? =
getAttribute(attr) { it.getString(0) }
fun Resources.Theme.getColorAttribute(#AttrRes attr: Int, defaultValue: Int = 0): Int =
getAttribute(attr) { it.getColor(0, defaultValue) }
#Composable
fun getDimensionAttribute(#AttrRes attr: Int, defaultValue: Float = 0f): Float =
LocalContext.current.theme.getDimensionAttribute(attr, defaultValue)
#Composable
fun getStringAttribute(#AttrRes attr: Int): String? =
LocalContext.current.theme.getStringAttribute(attr)
#Composable
fun getColorAttribute(#AttrRes attr: Int, defaultValue: Int = 0): Int =
LocalContext.current.theme.getColorAttribute(attr, defaultValue)
For getting color from attributes I use this composable function:
#Composable
fun getColor(color: Int): Color {
return colorResource(LocalContext.current.getColorFromAttrs(color).resourceId)
}
fun Context.getColorFromAttrs(attr: Int): TypedValue {
return TypedValue().apply {
theme.resolveAttribute(attr, this, true)
}
}
Usages:
val color: Color = getColor(R.attr.colorText)

Categories

Resources