Compose 主题的构成

Jetpack Compose 中的主题由许多更低级别的结构和相关的 API 组成。这些可以在 源代码 中看到 MaterialTheme,并且也可以应用于自定义设计系统。

主题系统类

主题通常由多个子系统组成,这些子系统对常见的视觉和行为概念进行分组。这些系统可以使用具有主题值的类来建模。

例如,MaterialTheme 包含 ColorScheme(颜色系统)、Typography(排版系统)和 Shapes(形状系统)。

@Immutable
data class ColorSystem(
    val color: Color,
    val gradient: List<Color>
    /* ... */
)

@Immutable
data class TypographySystem(
    val fontFamily: FontFamily,
    val textStyle: TextStyle
)
/* ... */

@Immutable
data class CustomSystem(
    val value1: Int,
    val value2: String
    /* ... */
)

/* ... */

主题系统 CompositionLocal

主题系统类作为 CompositionLocal 实例隐式提供给 Composition 树。这允许在可组合函数中静态引用主题值。

要了解更多关于 CompositionLocal 的信息,请查看 使用 CompositionLocal 的本地范围数据指南

val LocalColorSystem = staticCompositionLocalOf {
    ColorSystem(
        color = Color.Unspecified,
        gradient = emptyList()
    )
}

val LocalTypographySystem = staticCompositionLocalOf {
    TypographySystem(
        fontFamily = FontFamily.Default,
        textStyle = TextStyle.Default
    )
}

val LocalCustomSystem = staticCompositionLocalOf {
    CustomSystem(
        value1 = 0,
        value2 = ""
    )
}

/* ... */

主题函数

主题函数是入口点和主要 API。它使用 CompositionLocalProvider 构造主题系统 CompositionLocal 的实例(使用任何需要的实际值和逻辑),并将其提供给 Composition 树。content 参数允许嵌套的可组合项访问相对于层次结构的主题值。

@Composable
fun Theme(
    /* ... */
    content: @Composable () -> Unit
) {
    val colorSystem = ColorSystem(
        color = Color(0xFF3DDC84),
        gradient = listOf(Color.White, Color(0xFFD7EFFF))
    )
    val typographySystem = TypographySystem(
        fontFamily = FontFamily.Monospace,
        textStyle = TextStyle(fontSize = 18.sp)
    )
    val customSystem = CustomSystem(
        value1 = 1000,
        value2 = "Custom system"
    )
    /* ... */
    CompositionLocalProvider(
        LocalColorSystem provides colorSystem,
        LocalTypographySystem provides typographySystem,
        LocalCustomSystem provides customSystem,
        /* ... */
        content = content
    )
}

主题对象

访问主题系统是通过具有便捷属性的对象完成的。为了保持一致性,该对象通常与主题函数同名。属性只是获取当前 CompositionLocal。

// Use with eg. Theme.colorSystem.color
object Theme {
    val colorSystem: ColorSystem
        @Composable
        get() = LocalColorSystem.current
    val typographySystem: TypographySystem
        @Composable
        get() = LocalTypographySystem.current
    val customSystem: CustomSystem
        @Composable
        get() = LocalCustomSystem.current
    /* ... */
}