FrankMonza
FrankMonza

Reputation: 2044

How to change color on a specific app variant in Android Jetpack Compose?

I was used to override XML resources in values within specific app variants but i cannot do that anymore in jetpack compose so i was wondering which is a good approach with the new library without using any XML at all.

My theming is in a module and that module doesn't know anything about the app variants and i would like it to stay so. Which means that i cannot create a AppVariantColors class for each variant since i would not be able to reference it.

Should i pass the palette to the theme composable?

EDIT: what i am doing now is the following:

First i define a palette class with a set of color variants i will then use in the real variants:

enum class AppColorPalette {
    DARK_BLUE,
    DARK_RED,
    LIGHT_BLUE,
    LIGHT_RED
}

Then i create an app theme passing the palette

@Composable
fun AppTheme(
    dims: AppDims = appDims(),
    palette: AppColorPalette = AppColorPalette.DARK_BLUE,
    colors: AppColors = appColors(colorPalette = palette),
    typography: AppTypography = appTypography(colors, dims),
    shapes: AppShapes = appShapes(),
    content: @Composable () -> Unit,
) {
    CompositionLocalProvider(
        LocalAppColors provides colors,
        LocalAppDims provides dims,
        LocalAppShapes provides shapes,
        LocalAppTypography provides typography,
    ) {
        MaterialTheme(
            colors = colors.materialColors,
            typography = typography.materialTypography,
            shapes = shapes.materialShapes,
            content = content,
        )
    }
}

Finally i create app Colors composable based on the palette

@Composable
fun appColors(colorPalette: AppColorPalette): AppColors = when (colorPalette) {
    AppColorPalette.DARK_BLUE -> darkAppColorsBlueVariant
    ...
}

Where colors are defined something like this:

private val darkAppColorsBlueVariant = darkAppColors.copy(
    highEmphasis = AppColorsPalette.WhiteA100,
    midEmphasis = AppColorsPalette.WhiteA50,
    materialColors = darkColors(
        primary = AppColorsPalette.DarkGrey900,
    )
)

Basically doing so i can use the BuildConfig approach having to just select the color variant based on the theme

Upvotes: 2

Views: 2124

Answers (2)

Gabriele Mariotti
Gabriele Mariotti

Reputation: 364730

You can use the same approach.
Just config your build variant or product flavor in the build.gradle file then in your module define the MaterialTheme object (using for example the Themes.kt file in the different modules):

MaterialTheme(
    colors = …,
    typography = …,
    shapes = …
) {
    // app content
}

Or use your approach described in the updated question, using a single MaterialTheme object with the different colors defined in the single variants.

Upvotes: 1

Some random IT boy
Some random IT boy

Reputation: 8467

One way could be through BuildConfig fields on your build.gradle (app) file.

First define your flavors:

android {
  // other stuff
  flavorDimensions "base"
  productFlavors {
    cocacola {
      dimension "base"
      // cocacola is red :)
      buildConfigField "int", "accentColor", "0xFF0000"
    }
    pepsi {
      dimension "base"
      // pepsi is blue
      buildConfigField "int", "accentColor", "0x00FF00"
    }

  }
}

This will autogenerate a BuildConfig.java that you can access through Kotlin:

public final class BulildConfig {
  public static final int accentColor = 0xFF000; // depending on the flavor built
}

Then you can reference this static values from the place you define the material theme similar to how @Philip Dukov suggested

private val AppPalette = lightColors(
    accent = Color(BuildConfig.accentColor)
)

MaterialTheme(
    colors = AppPalette,
    typography = …,
    shapes = …,
    content = …
)

Upvotes: 0

Related Questions