Anatomie d'un thème dans Compose

Les thèmes de Jetpack Compose sont constitués d'un certain nombre de constructions de niveau inférieur et d'API associées. Ils sont visibles dans le code source de MaterialTheme et peuvent également être appliqués dans des systèmes de conception personnalisés.

Classes de systèmes de thèmes

Un thème est généralement composé d'un certain nombre de sous-systèmes qui regroupent des éléments visuels et concepts du comportement. Ces systèmes peuvent être modélisés avec des classes ayant des valeurs de thématisation.

Par exemple, MaterialTheme inclut ColorScheme (système de couleurs), Typography (système typographique) et Shapes (système de formes).

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

/* ... */

CompositionLocals de systèmes de thèmes

Les classes de systèmes de thèmes sont fournies implicitement à l'arborescence de composition en tant qu'instances CompositionLocal. Cela permet de référencer des valeurs de thématisation de manière statique dans des fonctions modulables.

Pour en savoir plus sur CompositionLocal, consultez le guide Données à champ d'application local avec 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 = ""
    )
}

/* ... */

Fonction de thème

La fonction de thème est le point d'entrée et l'API principale. Elle construit des instances de CompositionLocals de systèmes de thèmes, en utilisant les valeurs réelles de n'importe quelle logique requise, fournies à l'arborescence de composition avec CompositionLocalProvider. Le paramètre content permet aux composables imbriqués d'accéder aux valeurs de thématisation relatives à la hiérarchie.

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

Objet de thème

L'accès aux systèmes de thème s'effectue à l'aide d'un objet doté de propriétés pratiques. Par souci de cohérence, l'objet est généralement nommé de la même manière que la fonction de thème. Les propriétés obtiennent simplement le CompositionLocal actuel.

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