我正在为Compose中的应用程序创建一个库,该库旨在容纳所有需要的视图组件.这个库还需要有一个定制的主题.尤其是 colored颜色 和字体,因 for each 使用库的应用程序都将拥有完全自定义的 colored颜色 和字体.

当我想创建这个主题时,我的问题出现了.如果我在库中保留主题和所有 colored颜色 分配,效果很好,但我需要能够更改客户端应用程序中每个主题变量的 colored颜色 .

在本例中,假设我想用自定义 colored颜色 在一个对话框中定义ActionBar的不同部分.

我已经try 通过CompositionLocalProvider来实现这一点,只要我保持我在库中定义的 colored颜色 ,并且每个 colored颜色 的定义与https://m3.material.io/theme-builder#/custom提供的 colored颜色 相同,它就可以正常工作.

val md_theme_light_primary = Color(0xFF6750A4)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)

真正的症结现在出现了.假设我已经在我的库中定义了 colored颜色 DialogActionBarText.在每个使用库的客户端应用程序中,有没有办法只显示为设置它们而定义的 colored颜色 变量?下面是一个小的示例片段

/** Colors */
class TestColors(
    dialogActionBarColor: Color,
    isLight: Boolean
) {
    var dialogActionBarColor by mutableStateOf(dialogActionBarColor)
    var isLight by mutableStateOf(isLight)

    fun copy(
        dialogActionBarColor: Color = this.dialogActionBarColor,
        isLight: Boolean = this.isLight
    ): TestColors = TestColors(
        dialogActionBarColor,
        isLight
    )
    fun updateColorFrom(other: TestColors) {
        dialogActionBarColor = other.dialogActionBarColor
    }
}

fun getLightColors(): TestColors = TestColors(
    dialogActionBarColor = dialogActionBarLight,
    isLight = true
)

fun getDarkColors(): TestColors = TestColors(
    dialogActionBarColor = dialogActionBarDark,
    isLight = true
)

val dialogActionBarLight: Color = Color(0xFFAABBCC)
val dialogActionBarDark: Color = Color(0xFF112233)

val LocalColors = staticCompositionLocalOf{ getLightColors() }

/** Fonts */

private val myFont = FontFamily(
    Font(R.font.open_sans_regular, FontWeight.Normal)
)

data class AppTypography(
    val h1: TextStyle = TextStyle(
        fontFamily = myFont,
        fontWeight = FontWeight.Normal,
        fontSize = 24.sp
    ),
    val h2: TextStyle = TextStyle(
        fontFamily = myFont,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp
    )
)
internal val LocalTypography = staticCompositionLocalOf { AppTypography() }

/** Theme */

object TestTheme {
    val colors: TestColors
        @Composable
        @ReadOnlyComposable
        get() = LocalColors.current
    val fonts: AppColors
        @Composable
        @ReadOnlyComposable
        get() = LocalColors.current

}
@Composable
fun TestTheme(
    colors: TestColors = TestTheme.colors,
    typography: TestTypography = TestTheme.fonts
    dimensions: TestDimensions...,
    content: @Composable () -> Unit
) {

    val rememberedColors = remember { colors.copy() }.apply { updateColorFrom(colors) }
    CompositionLocalProvider(
        LocalColors provides rememberedColors,
        LocalTypography provides typography,
        LocalDimensions provides dimensions
    ) {
        content()
    }
}

我想要的是将每个 colored颜色 变量对话框ActionBarLight和-Dark公开给客户端应用程序,这样就可以很容易地设置它们,同时将其余的主题和 colored颜色 设置保留在客户端应用程序之外. 同样的原则适用于字体,它可以在每个客户端应用程序中不同,所以我需要能够公开myFont变量.

我的目标是在客户端应用程序中用最少的代码来定义 colored颜色 ,所以仅仅创建一个重复的主题有点违背了最初试图分离它的目的.

对如何实现这一点或类似的东西有什么 idea 吗?

换句话说,我如何获得与在Compose中使用某个库覆盖应用程序中某个库中的XML资源值相同的结果?

推荐答案

我想你是对的.

您只需将您的 colored颜色 设置为数据类,并公开您希望客户端应用程序能够定制的值,例如

data class TestColors(
    val mutableColor1: Color = Color.Red,
    val mutableColor2: Color = Color.White,
    val mutableColor3: Color = Color.Blue,
) {
    val immutableColor1 = Color.Red
    val immutableColor2 = Color.White
    val immutableColor3 = Color.Blue
}

然后使用本地合成,就像您所做的那样.

然而,你的主题不会像你拥有的那样工作,你不能访问CompositionLocalProvider以外的LocalSomething.current(在你实际设置它之前).

您需要对其进行如下重构:

@Composable
fun TestTheme(
    colors: TestColors = TestColors(),
    typography: TestTypography = TestTypography(),
    dimensions: TestDimensions = TestDimensions(),
    content: @Composable () -> Unit
) {

    CompositionLocalProvider(
        LocalColors provides colors,
        LocalTypography provides typography,
        LocalDimensions provides dimensions
    ) {
        content()
    }
}

然后让客户端应用程序简单地定制可变属性并直接使用您的主题:

@Composable
fun ClientApp() {
    val colors = TestColors(...)
    TestTheme(colors = colors) {
        ...
    }
}

Android相关问答推荐

当我的Log.i()不在主线程中时,如何在我的logcat中显示它?

有没有办法知道每台安卓设备上的通知限制?

如何将子零部件的大小调整为可以调整大小的父组件大小?

用于小部件泄漏警告的伙伴对象中的Kotlin Lateinit

如何在初始合成期间在可组合函数中调用/获取远程API中的数据[防止无限重组]

如何检测低性能 Android 设备进行条件动画渲染?

Android 不在后台更新位置

有没有办法让协程通道在接收时遵循特定的顺序而不是先进先出

在本地通知中设置自定义声音

在一个函数中组合相同的流 struct

在单元测试下断言协程未完成

在 Android Studio 中获取更新版本的 Picasso 库的错误警告消息

在移动设备上看到时如何增加 PasswordField 文本?

如何在 BottomBar jetpack compose 中删除选定的椭圆项目 colored颜色

如何在最后一个可见项目之后计算惰性列中的空白空间

如何为具有不同屏幕尺寸但相同密度的手机创建响应式布局?

jetpack compose 中的可点击指示是什么?

0dp 大小的可组合文件是否可以组合?

react-native-config 在发布版本中不起作用

Google Play 服务登录在 Unity Android 上无法正常运行