Principes de base des styles

Il existe trois façons d'adopter des styles dans votre application :

  1. Utilisez-le directement sur les composants existants qui exposent un paramètre Style.
  2. Appliquez un style avec Modifier.styleable sur les composables de mise en page qui n'acceptent pas de paramètre Style.
  3. Dans votre propre système de conception personnalisé, utilisez Modifier.styleable{} et exposez un paramètre de style sur vos propres composants.

Propriétés disponibles dans les styles

Les styles sont compatibles avec de nombreuses propriétés identiques à celles des modificateurs. Toutefois, tout ce qui est un modificateur ne peut pas être répliqué avec un style. Vous avez toujours besoin de modificateurs pour certains comportements, comme les interactions, le dessin personnalisé ou l'empilement des propriétés.

Regroupement Propriétés Héritée par les enfants
Mise en page et taille
Marges intérieures contentPadding (intérieur) et externalPadding (extérieur). Disponibles en versions directionnelle, horizontale, verticale et sur tous les côtés. Non
Dimensions fillWidth/Height/Size() et width, height et size (accepte les fractions Dp, DpSize ou Float). Non
Positionnement left/top/right/bottom. Non
Apparence visuelle
Remplissage background et foreground (compatible avec Color ou Brush). Non
Bordures borderWidth, borderColor et borderBrush. Non
Forme shape Non, mais utilisé en combinaison avec d'autres propriétés. clip et border utilisent cette forme définie.
Ombres dropShadow, innerShadow Non
Transformations
Mouvement spatial de la couche graphique translationX, translationY, scaleX/Y, rotationX/Y/Z Non
Contrôle alpha, zIndex (ordre d'empilement) et transformOrigin (point d'ancrage) Non
Typographie
Styles textStyle, fontSize, fontWeight, fontStyle et fontFamily Oui
Coloration contentColor et contentBrush. Il est également utilisé pour le style des icônes. Oui
Paragraphe lineHeight, letterSpacing, textAlign, textDirection, lineBreak et hyphens. Oui
Décoration textDecoration, textIndent et baselineShift. Oui

Utiliser des styles directement sur les composants avec des paramètres de style

Les composants qui exposent un paramètre Style vous permettent de définir leur style :

BaseButton(
    onClick = { },
    style = { }
) {
    BaseText("Click me")
}

Dans le lambda de style, vous pouvez définir différentes propriétés, telles que externalPadding ou background :

BaseButton(
    onClick = { },
    style = { background(Color.Blue) }
) {
    BaseText("Click me")
}

Pour obtenir la liste complète des propriétés compatibles, consultez Propriétés disponibles dans les styles.

Appliquer des styles à l'aide de modificateurs pour les composants sans paramètre existant

Pour les composants qui ne disposent pas de paramètre de style intégré, vous pouvez toujours appliquer des styles avec le modificateur styleable. Cette approche est également utile lorsque vous développez vos propres composants personnalisés.

Row(
    modifier = Modifier.styleable { }
) {
    BaseText("Content")
}

Comme pour le paramètre style, vous pouvez inclure des propriétés telles que background ou padding dans le lambda.

Row(
    modifier = Modifier.styleable {
        background(Color.Blue)
    }
) {
    BaseText("Content")
}

Plusieurs modificateurs Modifier.styleable enchaînés sont additifs avec les propriétés non héritées sur le composable appliqué, se comportant de la même manière que plusieurs modificateurs définissant les mêmes propriétés. Pour les propriétés héritées, elles sont remplacées et le dernier modificateur styleable de la chaîne définit les valeurs.

Lorsque vous utilisez Modifier.styleable, vous pouvez également créer et fournir un StyleState à utiliser avec le modificateur pour appliquer un style basé sur l'état. Pour en savoir plus, consultez État et animations avec les styles.

Définir un style autonome

Vous pouvez définir un style autonome à des fins de réutilisation :

val style = Style { background(Color.Blue) }

Vous pouvez ensuite transmettre ce style défini au paramètre de style d'un composable ou avec Modifier.styleable. Lorsque vous utilisez Modifier.styleable, vous devez également créer un objet StyleState. StyleState est abordé en détail dans la documentation État et animations avec les styles.

L'exemple suivant montre comment appliquer un style directement via les paramètres intégrés d'un composant ou via un Modifier.styleable :

val style = Style { background(Color.Blue) }

// built in parameter
BaseButton(onClick = { }, style = style) {
    BaseText("Button")
}

// modifier styleable
val styleState = remember { MutableStyleState(null) }
Column(
    Modifier.styleable(styleState, style)
) {
    BaseText("Column content")
}

Vous pouvez également transmettre ce style à plusieurs composants :

val style = Style { background(Color.Blue) }

// built in parameter
BaseButton(onClick = { }, style = style) {
    BaseText("Button")
}
BaseText("Different text that uses the same style parameter", style = style)

// modifier styleable
val columnStyleState = remember { MutableStyleState(null) }
Column(
    Modifier.styleable(columnStyleState, style)
) {
    BaseText("Column")
}
val rowStyleState = remember { MutableStyleState(null) }
Row(
    Modifier.styleable(rowStyleState, style)
) {
    BaseText("Row")
}

Ajouter plusieurs propriétés de style

Vous pouvez ajouter plusieurs propriétés de style en définissant différentes propriétés sur chaque ligne :

BaseButton(
    onClick = { },
    style = {
        background(Color.Blue)
        contentPaddingStart(16.dp)
    }
) {
    BaseText("Button")
}

Contrairement au style basé sur les modificateurs, les propriétés dans les styles ne sont pas cumulatives. Les styles prennent la dernière valeur définie dans la liste des propriétés d'un bloc de style. Dans l'exemple suivant, l'arrière-plan est défini deux fois. TealColor est l'arrière-plan appliqué. Pour la marge intérieure, contentPaddingTop remplace la marge intérieure supérieure définie par contentPadding et ne combine pas les valeurs.

BaseButton(
    style = {
        background(Color.Red)
        // Background of Red is now overridden with TealColor instead
        background(TealColor)
        // All directions of padding are set to 64.dp (top, start, end, bottom)
        contentPadding(64.dp)
        // Top padding is now set to 16.dp, all other paddings remain at 64.dp
        contentPaddingTop(16.dp)
    },
    onClick = {
        //
    }
) {
    BaseText("Click me!")
}

Bouton avec deux couleurs d'arrière-plan définies et deux remplacements de contentPadding
Figure 1. Bouton avec deux couleurs d'arrière-plan définies et deux remplacements contentPadding.

Fusionner plusieurs objets de style

Vous pouvez créer plusieurs objets Style et les transmettre au paramètre de style de votre composable.

val style1 = Style { background(TealColor) }
val style2 = Style { contentPaddingTop(16.dp) }

BaseButton(
    style = style1 then style2,
    onClick = {

    },
) {
    BaseText("Click me!")
}

Bouton avec couleur d'arrière-plan et contentPaddingTop défini
Figure 2. Bouton avec une couleur d'arrière-plan et contentPaddingTop définis.

Lorsque plusieurs styles spécifient la même propriété, la dernière propriété définie est choisie. Étant donné que les propriétés ne sont pas cumulatives dans les styles, la dernière marge intérieure transmise remplace la valeur contentPaddingHorizontal définie par le contentPadding initial. De plus, la dernière couleur d'arrière-plan remplace celle définie par le style initial transmis.

val style1 = Style {
    background(Color.Red)
    contentPadding(32.dp)
}

val style2 = Style {
    contentPaddingHorizontal(8.dp)
    background(Color.LightGray)
}

BaseButton(
    style = style1 then style2,
    onClick = {

    },
) {
    BaseText("Click me!")
}

Dans ce cas, le style appliqué présente un arrière-plan gris clair et une marge intérieure de 32.dp, à l'exception de la marge intérieure de gauche et de droite, qui a une valeur de 8.dp.

Bouton avec contentPadding remplacé par différents styles
Figure 3. Bouton avec contentPadding remplacé par différents styles.

Héritage de style

Certaines propriétés de style, telles que contentColor et les propriétés liées au style de texte, se propagent aux composables enfants. Un style défini sur un composable enfant remplace le style parent hérité pour cet enfant spécifique.

Propagation du style avec les paramètres "style", "styleable" et "direct"
Figure 4. Propagation du style avec les paramètres Style, styleable et directs.
Priorité Méthode Effet
1 (la plus élevée) Arguments directs sur un composable Remplace tout. Par exemple, Text(color = Color.Red)
2 Paramètre de style Remplacements de style locaux Text(style = Style { contentColor(Color.Red)}
3 Chaîne de modificateurs Modifier.styleable{ contentColor(Color.Red) sur le composant lui-même.
4 (le plus faible) Styles parents Pour les propriétés pouvant être héritées (typographie/couleur) transmises par le parent.

Style parent

Vous pouvez définir des propriétés de texte (telles que contentColor) à partir du composable parent, et elles se propagent à tous les composables Text enfants.

val styleState = remember { MutableStyleState(null) }
Column(
    modifier = Modifier.styleable(styleState) {
        background(Color.LightGray)
        val blue = Color(0xFF4285F4)
        val purple = Color(0xFFA250EA)
        val colors = listOf(blue, purple)
        contentBrush(Brush.linearGradient(colors))
    },
) {
    BaseText("Children inherit", style = { width(60.dp) })
    BaseText("certain properties")
    BaseText("from their parents")
}

Héritage des propriétés des composables enfants
Figure 5 : Héritage des propriétés des composables enfants.

Remplacement des propriétés par les enfants

Vous pouvez également définir un style sur un composable Text spécifique. Si le composable parent a un style défini, le style défini sur le composable enfant remplace celui du composable parent.

val styleState = remember { MutableStyleState(null) }
Column(
    modifier = Modifier.styleable(styleState) {
        background(Color.LightGray)
        val blue = Color(0xFF4285F4)
        val purple = Color(0xFFA250EA)
        val colors = listOf(blue, purple)
        contentBrush(Brush.linearGradient(colors))
    },
) {
    BaseText("Children can ", style = {
        contentBrush(Brush.linearGradient(listOf(Color.Red, Color.Blue)))
    })
    BaseText("override properties")
    BaseText("set by their parents")
}

Les composables enfants remplacent les propriétés parentes
Figure 6 : Les composables enfants remplacent les propriétés parentes.

Implémenter des propriétés de style personnalisées

Vous pouvez créer des propriétés personnalisées qui correspondent à des définitions de style existantes en utilisant des fonctions d'extension sur StyleScope, comme illustré dans l'exemple suivant :

fun StyleScope.outlinedBackground(color: Color) {
    border(1.dp, color)
    background(color)
}

Appliquez cette nouvelle propriété dans une définition de style :

val customExtensionStyle = Style {
    outlinedBackground(Color.Blue)
}

La création de propriétés stylables n'est pas prise en charge. Si votre cas d'utilisation nécessite une telle assistance, envoyez une demande de fonctionnalité.

Lire les valeurs CompositionLocal

Il est courant de stocker les jetons du système de conception dans un CompositionLocal, pour accéder aux variables sans avoir à les transmettre en tant que paramètres. Les styles peuvent accéder aux CompositionLocal pour récupérer les valeurs à l'échelle du système dans un style :

val buttonStyle = Style {
    contentPadding(12.dp)
    shape(RoundedCornerShape(50))
    background(Brush.verticalGradient(LocalCustomColors.currentValue.background))
}