Anatomia de um tema no Compose

Os temas no Jetpack Compose são compostos por várias construções de nível mais baixo e APIs relacionadas. Isso pode ser visto no código-fonte do MaterialTheme e também pode ser aplicado em sistemas de design personalizado.

Classes do sistema de temas

Um tema normalmente é composto por vários subsistemas que agrupam recursos visuais e conceitos comportamentais. Esses sistemas podem ser modelados com classes que têm valores de tema.

Por exemplo, o MaterialTheme inclui ColorScheme (sistema de cores), Typography (sistema de tipografia) e Shapes (sistema de formas).

@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     /* ... */ )  /* ... */

Locais de composição do sistema de temas

As classes do sistema de temas são fornecidas implicitamente à árvore de composição como instâncias CompositionLocal. Isso possibilita que os valores de temas sejam referenciados estaticamente em funções que podem ser compostas.

Para saber mais sobre a CompositionLocal, confira o Guia de dados com escopo local na 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 = ""     ) }  /* ... */

Função do tema

A função do tema é o ponto de entrada e a API principal. Ela cria instâncias da CompositionLocals do sistema de temas usando valores reais que qualquer lógica exige. Esses valores são fornecidos na árvore de composição com CompositionLocalProvider. O parâmetro content possibilita que elementos que podem ser compostos aninhados acessem valores de tema relacionados à hierarquia.

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

Objeto do tema

O acesso a sistemas de temas é feito usando um objeto com propriedades de conveniência. Para consistência, o objeto tende a receber o mesmo nome da função do tema. As propriedades simplesmente recebem a composição local atual.

// 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     /* ... */ }