【问题标题】:How to change color on a specific app variant in Android Jetpack Compose?如何在 Android Jetpack Compose 中更改特定应用变体的颜色?
【发布时间】:2021-09-05 05:48:49
【问题描述】:

我习惯于在特定应用程序变体中覆盖 XML 资源的值,但在 jetpack compose 中我不能再这样做了,所以我想知道在完全不使用任何 XML 的情况下,哪个是新库的好方法。

我的主题位于一个模块中,该模块对应用程序变体一无所知,我希望它保持不变。这意味着我无法为每个变体创建 AppVariantColors 类,因为我无法引用它。

我应该将调色板传递给可组合的主题吗?

编辑:我现在正在做的事情如下:

首先我定义了一个带有一组颜色变体的调色板类,然后我将在实际变体中使用:

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

然后我通过调色板创建一个应用程序主题

@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,
        )
    }
}

最后我创建了基于调色板可组合的应用颜色

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

颜色的定义如下:

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

基本上这样做我可以使用 BuildConfig 方法,只需根据主题选择颜色变体

【问题讨论】:

  • 你目前的方法有什么问题?

标签: android android-jetpack-compose


【解决方案1】:

一种方法是通过build.gradle(应用程序)文件中的BuildConfig 字段。

首先定义你的口味:

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"
    }

  }
}

这将自动生成一个您可以通过 Kotlin 访问的 BuildConfig.java

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

然后您可以从定义材质主题的位置引用此静态值,类似于@Philip Dukov 建议的方式

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

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

【讨论】:

  • 我在问题中给出的示例中对此进行了扩展,使用风味来选择调色板
  • 是的......使用 gradle 定义一个完整的主题可能有点麻烦......最好在 kotlin 中定义它们并在运行时选择正确的主题:)
【解决方案2】:

您可以使用相同的方法。
只需在 build.gradle 文件中配置您的构建变体或产品风格,然后在您的模块中定义 MaterialTheme 对象(例如使用不同模块中的 Themes.kt 文件):

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

或者使用更新后的问题中描述的方法,使用单个 MaterialTheme 对象,该对象在单个变体中定义了不同的颜色。

【讨论】:

  • 确实,但这意味着有很多冗余,因为我必须在每个变体中定义 MaterialTheme 类。我将用我现在所拥有的来编辑答案。
  • 所以现在我将在主题中定义不同的通用颜色风格(蓝色/红色/绿色),然后根据变体选择那些,这样我就可以避免在主题之外使用主题代码主题模块和主题模块不需要知道任何关于变体的事情
  • 您也可以只定义一个 MaterialTheme 对象,如您的问题中所述,应用在单个变体中定义的不同颜色。
  • 那么假设主题位于模块中并且对此一无所知,您将如何定义不同变体中的颜色?它不像 XML,您可以覆盖现有的 XML
  • 我没有抓住重点。如果您对此一无所知,如何覆盖现有的 XML?我将扩展我的示例,但它与 XML 方法相同。
猜你喜欢
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 2022-10-25
  • 2023-02-08
  • 1970-01-01
  • 2023-02-13
  • 2022-11-06
相关资源
最近更新 更多