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, benutzerdefiniertes Zeichnen oder das Stapeln von Properties sind weiterhin Modifikatoren erforderlich.

Gruppierung Properties Von untergeordneten Elementen übernommen
Layout und Größe
Abstand contentPadding (innen) und externalPadding (außen) Verfügbar in Varianten für Richtung, horizontal, vertikal und alle Seiten. Nein
Abmessungen fillWidth/Height/Size() und width, height und size (unterstützt Dp, DpSize oder Float Bruchteile) 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/Y, rotationX/Y/Z 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 trotzdem Stile 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 oder padding 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, können Sie auch einen StyleState erstellen und bereitstellen, der mit dem Modifikator verwendet werden soll, 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.

Das folgende Beispiel zeigt, 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 Stil-Properties hinzufügen

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

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

Eigenschaften in Stilen sind nicht additiv, anders als beim modifikatorbasierten Styling. Stile verwenden den zuletzt festgelegten Wert in der Liste der Properties innerhalb eines Stilblocks. Im folgenden Beispiel ist der Hintergrund zweimal festgelegt. Daher wird TealColor als Hintergrund angewendet. Bei contentPaddingTop überschreibt den oberen Abstand, der durch 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 mehrere Stile dieselbe Property angeben, wird die zuletzt festgelegte Property ausgewählt. Da Properties in Stilen nicht additiv sind, überschreibt der zuletzt übergebene Abstand den contentPaddingHorizontal durch das anfängliche contentPadding festgelegten. Außerdem überschreibt die letzte Hintergrundfarbe die durch den anfänglich übergebenen Stil festgelegte Hintergrundfarbe.

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 einen Abstand von 32.dp, mit Ausnahme des linken und rechten Abstands, der einen Wert von 8.dp hat.

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

Stilübernahme

Bestimmte Stil-Properties wie contentColor und Properties im Zusammenhang mit dem Textstil 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 wie contentColor vom ü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 Stil-Properties 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))
}