Search code examples
androidandroid-jetpack-composeandroid-theme

Compose theme inconsistent behavior


I have a theme in my app set up like so:

//use light colors for dark mode
private val ConceptualSystemsDarkColorScheme = darkColorScheme(
    primary = Yellowish,
    secondary = YellowishBright,
    tertiary = Orangeish,
    background = Color.Black,
    surface = Color.Black,
    onBackground = Color.Black,
)

//use dark colors for light mode
private val ConceptualSystemsLightColorScheme = lightColorScheme(
    primary = DarkYellowish,
    secondary = DarkYellowishDim,
    tertiary = DarkOrangeish,
    background = Yellowish,
    surface = Yellowish,
    onBackground = Yellowish,
)

@Composable
fun ConceptualSystemsTheme(
    useDarkTheme: Boolean = false, //never use Dark theme
    dynamicColor: Boolean = false,
    content: @Composable () -> Unit
) {
    val logger = LoggerFactory.getLogger("Theme")
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            logger.info("THEME: found build version : "
                    + Build.VERSION.SDK_INT + " >= " + Build.VERSION_CODES.S
                    + " : opting for dynamic system color scheme...")
            val context = LocalContext.current
            if(useDarkTheme) {
                logger.info("Using dark dynamic color scheme")
                dynamicDarkColorScheme(context)
            } else {
                logger.info("Using light dynamic color scheme")
                dynamicLightColorScheme(context)
            }
        }
        useDarkTheme -> {
            logger.info("Using dark color scheme")
            ConceptualSystemsDarkColorScheme
        }
        else -> {
            logger.info("Using light color scheme")
            ConceptualSystemsLightColorScheme
        }
    }

    MaterialTheme(
        shapes = MaterialTheme.shapes.copy(
            RoundedCornerShape(6.dp)
        ),
        colorScheme = colorScheme,
        typography = DefaultTypography,
        content = content
    )
}

Seems straightforward... however, I get mixed results. I call the Theme as normal:

setContent {
    ConceptualSystemsTheme {
        MainLayout(keepDriverNumber.collectAsState(initial = false))
    }
}

In one Activity, the background is yellow, as expected. In another activity, the background is black, and in another activity half of the background is yellow and the bottom half under a lazy column is black. Why is the theme behavior so inconsistent? Logcat shows that the light theme is being used every time, but the background is different in each activity... (by the way, the test system is running Android 9, and therefore dynamic themes are not a factor (confirmed by Logcat).


Solution

  • One thing that is not 100% clear is what you mean by activity? If you have two different activities you should set theme in both of them, but I suppose that you did that. Other thing that you should know is that not all elements take background color. For example

              TestTheme {
                Column {
                    Box(modifier = Modifier.fillMaxHeight(0.3f)) {
                        Text(modifier = Modifier.align(Alignment.Center), text = "Box")
                    }
                    Scaffold(
                        modifier = Modifier
                            .fillMaxHeight(0.4f)
                    ) { innerPadding ->
                        Text(text = "scafold")
                    }
                }
            }
    

    Will generate ui like this:

    image

    In Jetpack Compose, the Scaffold automatically applies the theme's colors to its components, such as the app bar, floating action button, etc. However, layout composables like Column, Row, Box, etc., don't have a default background. They are layout containers and don't render anything visible themselves. So maybe the easiest solution is to use Surface or Scaffold, or something similar as root component.