Grundlagen von Stilen

Es gibt drei Möglichkeiten, Stile in Ihrer App zu verwenden:

  1. Direkt für vorhandene Komponenten, die einen Style Parameter verfügbar machen.
  2. Mit Modifier.styleable einen Stil auf Layout Composables anwenden, die keinen Style Parameter akzeptieren.
  3. In Ihrem eigenen benutzerdefinierten Designsystem Modifier.styleable{} verwenden und einen Stilparameter für Ihre eigenen Komponenten verfügbar machen.

Verfügbare Properties für Stile

Stile unterstützen viele der gleichen Properties wie Modifikatoren. Allerdings kann nicht alles, was ein Modifikator ist, mit einem Stil repliziert werden. Für bestimmte Verhaltensweisen wie Interaktionen, benutzerdefinierte Zeichnungen oder das Stapeln von Properties sind weiterhin Modifikatoren erforderlich.

Gruppierung Properties Von untergeordneten Elementen übernommen
Layout und Größe
Content Padding (innen) - contentPadding(all: Dp)
- contentPadding(horizontal: Dp, vertical: Dp)
- contentPadding(start: Dp, top: Dp, end: Dp, bottom: Dp)
- contentPaddingHorizontal(value: Dp) / contentPaddingVertical(value: Dp)
- contentPaddingStart(value: Dp) / contentPaddingTop(value: Dp) / contentPaddingEnd(value: Dp) / contentPaddingBottom(value: Dp)
Nein
External Padding (außen) - externalPadding(all: Dp)
- externalPadding(horizontal: Dp, vertical: Dp)
- externalPadding(start: Dp, top: Dp, end: Dp, bottom: Dp)
- externalPaddingHorizontal(value: Dp) / externalPaddingVertical(value: Dp)
- externalPaddingStart(value: Dp) / externalPaddingTop(value: Dp) / externalPaddingEnd(value: Dp) / externalPaddingBottom(value: Dp)
Nein
Abmessungen fillWidth()/fillHeight()/fillSize() und width, height und size (unterstützt Dp, DpSize oder Float Brüche). Nein
Positionierung left/top/right/bottom-Offsets. Nein
Visuelles Erscheinungsbild
Füllen background und foreground (unterstützt Color oder Brush). Nein
Rahmen borderWidth, borderColor und borderBrush. Nein
Form shape Nein, wird aber in Verbindung mit anderen Properties verwendet. clip und border verwenden diese definierte Form.
Schatten dropShadow, innerShadow Nein
Transformationen
Räumliche Bewegung der Grafikebene translationX, translationY, scaleX/scaleY, rotationX/rotationY/rotationZ Nein
Steuerung alpha, zIndex (Stapelreihenfolge) und transformOrigin (Drehpunkt) Nein
Typografie
Stil textStyle, fontSize, fontWeight, fontStyle und fontFamily Ja
Farbe contentColor und contentBrush. Wird auch für das Design von Symbolen verwendet. Ja
Absatz lineHeight, letterSpacing, textAlign, textDirection, lineBreak und hyphens. Ja
Dekoration textDecoration, textIndent und baselineShift. Ja

Stile direkt auf Komponenten mit Stilparametern anwenden

Bei Komponenten, die einen Style-Parameter verfügbar machen, können Sie das Design festlegen:

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

In der Stil-Lambda können Sie verschiedene Properties festlegen, z. B. externalPadding oder background:

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

Eine vollständige Liste der unterstützten Properties finden Sie unter Verfügbare Properties für Stile.

Stile mit Modifikatoren auf Komponenten ohne vorhandenen Parameter anwenden

Für Komponenten ohne integrierten Stilparameter können Sie Stile trotzdem mit dem Modifikator styleable anwenden. Dieser Ansatz ist auch nützlich, wenn Sie eigene benutzerdefinierte Komponenten entwickeln.

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

Ähnlich wie beim Parameter style können Sie Properties wie background, contentPadding oder externalPadding in die Lambda einfügen.

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

Mehrere verkettete Modifier.styleable-Modifikatoren sind additiv mit nicht übernommenen Properties auf dem angewendeten Composables und verhalten sich ähnlich wie mehrere Modifikatoren, die dieselben Properties definieren. Bei übernommenen Properties werden diese überschrieben und der letzte styleable-Modifikator in der Kette legt die Werte fest.

Wenn Sie Modifier.styleable verwenden, sollten Sie auch einen StyleState erstellen und bereitstellen, der mit dem Modifikator verwendet wird, um zustandsbasiertes Design anzuwenden. Weitere Informationen finden Sie unter Zustand und Animationen mit Stilen.

Eigenständigen Stil definieren

Sie können einen eigenständigen Stil definieren, um ihn wiederzuverwenden:

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

Sie können diesen definierten Stil dann an den Stilparameter eines Composables oder mit Modifier.styleable übergeben. Wenn Sie Modifier.styleable verwenden, müssen Sie auch ein StyleState-Objekt erstellen. StyleState wird ausführlich in der Zustand und Animationen mit Stilen Dokumentation behandelt.

Im folgenden Beispiel wird gezeigt, wie Sie einen Stil entweder direkt über die integrierten Parameter einer Komponente oder über einen Modifier.styleable anwenden können:

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

Sie können diesen Stil auch an mehrere Komponenten übergeben:

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

Mehrere Stileigenschaften hinzufügen

Sie können mehrere Stileigenschaften hinzufügen, indem Sie in jeder Zeile unterschiedliche Properties festlegen:

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

Properties in Stilen sind nicht additiv, anders als beim modifikatorbasierten Design. Stile verwenden den zuletzt festgelegten Wert in der Liste der Properties innerhalb eines Stilblocks. Im folgenden Beispiel wird der Hintergrund zweimal festgelegt. Daher wird TealColor als Hintergrund angewendet. Bei der Auffüllung überschreibt contentPaddingTop die obere Auffüllung, die mit contentPadding festgelegt wurde, und kombiniert die Werte nicht.

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!")
}

Button mit zwei festgelegten Hintergrundfarben und zwei Überschreibungen für „contentPadding“
Abbildung 1 Schaltfläche mit zwei festgelegten Hintergrundfarben und zwei contentPadding-Überschreibungen.

Mehrere Stilobjekte zusammenführen

Sie können mehrere Stilobjekte erstellen und sie an den Stilparameter Ihres Composables übergeben.

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

BaseButton(
    style = style1 then style2,
    onClick = {

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

Schaltfläche mit Hintergrundfarbe und „contentPaddingTop“ festgelegt
Abbildung 2. Schaltfläche mit festgelegter Hintergrundfarbe und contentPaddingTop.

Wenn in mehreren Stilen dieselbe Property angegeben ist, wird die zuletzt festgelegte Property ausgewählt. Da Properties in Stilen nicht additiv sind, überschreibt die zuletzt übergebene Auffüllung die contentPaddingHorizontal mit dem ursprünglichen contentPadding festgelegte. Außerdem überschreibt die letzte Hintergrundfarbe die Hintergrundfarbe, die mit dem ursprünglich übergebenen Stil festgelegt wurde.

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!")
}

In diesem Fall hat das angewendete Design einen hellgrauen Hintergrund und eine Auffüllung von 32.dp, mit Ausnahme der linken und rechten Auffüllung, die einen Wert von 8.dp hat.

Schaltfläche mit „contentPadding“, das durch verschiedene Stile überschrieben wird
Abbildung 3. Schaltfläche mit contentPadding, die von verschiedenen Stilen überschrieben wird.

Stilübernahme

Bestimmte Stileigenschaften wie contentColor und textstilbezogene Properties werden an die untergeordneten Composables weitergegeben. Ein Stil, der für ein untergeordnetes Composables festgelegt wurde, überschreibt das übernommene übergeordnete Design für dieses bestimmte untergeordnete Element.

Stilübertragung mit den Parametern „style“, „styleable“ und „direct“
Abbildung 4 Stilweitergabe mit Style, styleable und direkten Parametern.
Priorität Methode Effekt
1 (höchste Priorität) Direkte Argumente für ein Composables Überschreibt alles, z. B. Text(color = Color.Red)
2 Stilparameter Lokaler Stil überschreibt Text(style = Style { contentColor(Color.Red)}
3 Modifikatorkette Modifier.styleable{ contentColor(Color.Red) für die Komponente selbst.
4 (niedrigste Priorität) Übergeordnete Stile Für Properties, die übernommen werden können (Typografie/Farbe), die vom übergeordneten Element weitergegeben werden.

Übergeordnetes Design

Sie können Texteigenschaften (z. B. contentColor) aus dem übergeordneten Composables festlegen. Sie werden an alle untergeordneten Text-Composables weitergegeben.

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

Property-Übernahme von untergeordneten Composables
Abbildung 5. Property-Übernahme von untergeordneten Composables.

Überschreibung von Properties durch untergeordnete Elemente

Sie können auch das Design für ein bestimmtes Text-Composables festlegen. Wenn für das übergeordnete Composables ein Design festgelegt ist, überschreibt das für das untergeordnete Composables festgelegte Design das Design des übergeordneten Composables.

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

Untergeordnete Composables überschreiben übergeordnete Eigenschaften
Abbildung 6 Untergeordnete Composables überschreiben übergeordnete Properties.

Benutzerdefinierte Stileigenschaften implementieren

Sie können benutzerdefinierte Properties erstellen, die vorhandenen Stildefinitionen zugeordnet werden, indem Sie Erweiterungsfunktionen für StyleScope verwenden, wie im folgenden Beispiel gezeigt:

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

Wenden Sie diese neue Property in einer Stildefinition an:

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

Das Erstellen neuer styleable Properties wird nicht unterstützt. Wenn Sie diese Unterstützung benötigen, senden Sie einen Feature Request.

CompositionLocal-Werte lesen

Es ist üblich, Designsystem-Tokens in einem CompositionLocal zu speichern, um auf die Variablen zuzugreifen, ohne sie als Parameter übergeben zu müssen. Stile können auf CompositionLocals zugreifen, um systemweite Werte in einem Stil abzurufen:

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