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 实例的形式隐式提供给组合树。这样就可以在可组合函数中静态引用主题值。

如需详细了解 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 = ""  ) } /* ... */

Theme 函数

Theme 函数是入口点和主 API。该函数会构造主题系统 CompositionLocalProvider 的实例(使用任何逻辑所需的实际值),这些实例会通过 CompositionLocal 提供给组合树。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  ) }

Theme 对象

使用具有便捷属性的对象来访问主题系统。为了保持一致性,对象往往采用与 Theme 函数相同的名称。这些属性只会获取当前的 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  /* ... */ }