Aufbau eines Designs in der Funktion "Compose"

Themes in Jetpack Compose bestehen aus einer Reihe von Low-Level-Konstrukten und zugehörigen APIs. Sie sind im Quellcode von MaterialTheme zu sehen und können auch in benutzerdefinierten Designsystemen angewendet werden.

Design-Systemklassen

Ein Design besteht in der Regel aus einer Reihe von Subsystemen, in denen gemeinsame visuelle und verhaltensbezogene Konzepte gruppiert werden. Diese Systeme können mit Klassen modelliert werden, die Designwerte haben.

MaterialTheme enthält beispielsweise ColorScheme (Farbsystem), Typography (Typografiesystem) und Shapes (Formsystem).

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

/* ... */

Lokale Einstellungen für die Zusammensetzung des Designsystems

Themensystemklassen werden dem Kompositionsbaum implizit als CompositionLocal-Instanzen bereitgestellt. So können Designwerte statisch in zusammensetzbaren Funktionen referenziert werden.

Weitere Informationen zu CompositionLocal finden Sie im Leitfaden zu lokal begrenzten Daten mit 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 = ""
    )
}

/* ... */

Designfunktion

Die Themenfunktion ist der Einstiegspunkt und die primäre API. Es werden Instanzen der CompositionLocal des Themasystems erstellt – mit echten Werten und der erforderlichen Logik –, die dem Kompositionsbaum mit CompositionLocalProvider bereitgestellt werden. Mit dem Parameter content können verschachtelte Composables auf Designwerte relativ zur Hierarchie zugreifen.

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

Designobjekt

Der Zugriff auf Designsysteme erfolgt über ein Objekt mit Convenience-Properties. Aus Gründen der Einheitlichkeit wird das Objekt in der Regel genauso benannt wie die Themenfunktion. Die Eigenschaften rufen einfach die aktuelle Komposition lokal ab.

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