Issue
Hey I am new in jetpack compose. I tried to set window background color black and white according to theme. When I created custom theme and set background color my text color will be black.
theme.kt
package com.vivek.sportsresult.ui.theme
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import com.google.accompanist.systemuicontroller.rememberSystemUiController
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80,
background = Color.Black
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40,
background = Color.White
)
@Composable
fun SportsResultTheme(
darkTheme: Boolean = isDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val systemUiController = rememberSystemUiController()
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
}
}
if (darkTheme) {
systemUiController.setSystemBarsColor(
color = Color.Black
)
} else {
systemUiController.setSystemBarsColor(
color = Color.White
)
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
@Composable
fun isDarkTheme() = isSystemInDarkTheme()
@Composable
fun getBackgroundColor() = if (isDarkTheme()) {
DarkColorScheme.background
} else {
LightColorScheme.background
}
MainActivity.kt
package com.vivek.sportsresult
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import com.vivek.sportsresult.ui.theme.SportsResultTheme
import com.vivek.sportsresult.ui.theme.getBackgroundColor
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SportsResultTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = getBackgroundColor()
) {
Log.e("TAG", "onCreate: ")
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
SportsResultTheme {
Greeting("Android")
}
}
When I tried to use color = getBackgroundColor()
it not changing text color but if use color = MaterialTheme.colorScheme.background
it working correct on dark and white theme. I don't understand why? Can someone guide me on this?
Actual Output
Expected Output
Solution
When you use MaterialTheme.colorScheme.background
it works correctly because in that case the Surface
composable is able to determine the correct content color (that would be the contentColor
parameter) based on the background color which you set (which is the color
parameter).
However, when you use getBackgroundColor()
in dark mode you get back Color.Black
and since you are running your code on a device with Android 12 your theme is a dynamic color theme which was created here
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
and apparently does not contain any color that is exactly Color.Black
, i.e. that is exactly Color(0xFF000000)
, and thus the Surface
composable is unable to determine the correct content color.
When a given color is not found in the theme then the contentColor
is set to LocalContentColor.current
and it just happens that in your case this results in a black text on a black background.
You have 2 options:
- you can use
MaterialTheme.colorScheme.background
and let it determine thecontentColor
automatically based on your theme. - you can set both
color
andcontentColor
yourself like this
Surface(
modifier = Modifier.fillMaxSize(),
color = getBackgroundColor(),
contentColor = /* get and set some content color */,
)
This behavior is due to how Surface
contentColor
parameter default value is implemented by calling contentColorFor(color)
. See the Surface composable implementation and contentColorFor
implementation (in Android Studio you Ctrl/Cmd+click on them, or open the context menu > Go To > Implementation).
Answered By - Ma3x
Answer Checked By - Robin (JavaFixing Admin)