Grundlagen von Stilen

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

  1. Kann direkt für vorhandene Komponenten verwendet werden, die einen Style-Parameter enthalten.
  2. Wenden Sie einen Stil mit Modifier.styleable auf Layout-Composables an, die keinen Style-Parameter akzeptieren.
  3. Verwenden Sie Modifier.styleable{} in Ihrem eigenen benutzerdefinierten Designsystem und stellen Sie einen Stilparameter für Ihre eigenen Komponenten bereit.

Verfügbare Eigenschaften für Stile

Stile unterstützen viele der Eigenschaften, die auch von Modifizierern unterstützt werden. Allerdings kann nicht alles, was ein Modifizierer ist, mit einem Stil repliziert werden. Für bestimmte Verhaltensweisen wie Interaktionen, benutzerdefiniertes Zeichnen oder das Stapeln von Eigenschaften sind weiterhin Modifikatoren erforderlich.

Gruppierung Properties Von untergeordneten Elementen übernommen
Layout und Größe
Padding contentPadding (innen) und externalPadding (außen). Verfügbar in gerichteten, horizontalen, vertikalen und allseitigen Varianten. 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
Rahmenlinien borderWidth, borderColor und borderBrush. Nein
Form shape Nein, aber in Verbindung mit anderen Properties. 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
Umfassende Kontrolle alpha, zIndex (Stapelreihenfolge) und transformOrigin (Drehpunkt) Nein
Typografie
Stil textStyle, fontSize, fontWeight, fontStyle und fontFamily Ja
Färbung contentColor und contentBrush. Dies wird auch für die Formatierung von Symbolen verwendet. Ja
Paragraph 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 Styling festlegen:

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

Im Stil-Lambda können Sie verschiedene Eigenschaften festlegen, z. B. externalPadding oder background:

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

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

Stile mithilfe von Modifizierern für Komponenten ohne vorhandenen Parameter anwenden

Für Komponenten, die keinen integrierten Stilparameter haben, 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 Eigenschaften wie background oder padding in die Lambda-Funktion einfügen.

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

Mehrere verkettete Modifier.styleable-Modifikatoren werden mit nicht geerbten Eigenschaften des angewendeten Composables addiert. Das Verhalten ähnelt dem von mehreren Modifikatoren, die dieselben Eigenschaften definieren. Bei übernommenen Attributen werden diese überschrieben und die Werte werden durch den letzten styleable-Modifikator in der Kette festgelegt.

Wenn Sie Modifier.styleable verwenden, sollten Sie auch eine StyleState erstellen und bereitstellen, die mit dem Modifikator verwendet werden soll, um statusbasiertes Styling anzuwenden. Weitere Informationen finden Sie unter Status 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 einer zusammensetzbaren Funktion oder mit Modifier.styleable übergeben. Wenn Sie Modifier.styleable verwenden, müssen Sie auch ein StyleState-Objekt erstellen. StyleState wird ausführlich in der Dokumentation Status und Animationen mit Stilen behandelt.

Im folgenden Beispiel sehen Sie, wie Sie einen Stil entweder direkt über die integrierten Parameter einer Komponente oder über ein 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 Style-Eigenschaften hinzufügen, indem Sie für jede Zeile unterschiedliche Eigenschaften festlegen:

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

Eigenschaften in Stilen sind nicht additiv, im Gegensatz zu Modifikator-basierten Stilen. Bei Formatierungen wird der zuletzt festgelegte Wert in der Liste der Eigenschaften innerhalb eines Formatierungsblocks verwendet. Im folgenden Beispiel wird der Hintergrund zweimal festgelegt. TealColor ist der angewendete Hintergrund. Bei der Auffüllung überschreibt contentPaddingTop die mit contentPadding festgelegte obere Auffüllung und die Werte werden nicht kombiniert.

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

Schaltfläche 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 Style-Objekte erstellen und sie an den Style-Parameter 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“ < 0x0A>
Abbildung 2. Schaltfläche mit Hintergrundfarbe und contentPaddingTop.

Wenn in mehreren Formatierungen dieselbe Eigenschaft angegeben wird, wird die zuletzt festgelegte Eigenschaft ausgewählt. Da Attribute in Styles nicht additiv sind, wird das zuletzt übergebene Padding durch das anfängliche contentPadding überschrieben.contentPaddingHorizontal Außerdem wird die Hintergrundfarbe, die durch den ursprünglichen Stil festgelegt wurde, durch die letzte Hintergrundfarbe überschrieben.

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 Styling einen hellgrauen Hintergrund und 32.dp-Abstand, mit Ausnahme des linken und rechten Abstands, der den Wert 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 Eigenschaften werden an die untergeordneten Composables weitergegeben. Ein Stil, der für ein untergeordnetes Composable festgelegt ist, überschreibt den geerbten übergeordneten Stil für dieses untergeordnete Element.

Stilübertragung mit den Parametern „Style“, „styleable“ und „direct“
Abbildung 4: Stilübertragung mit Style, styleable und direkten Parametern
Priorität Methode Effekte
1 (Höchste) Direkte Argumente für eine Composable-Funktion Überschreibt alles, z. B. Text(color = Color.Red)
2 Stilparameter Lokale Stilüberschreibungen Text(style = Style { contentColor(Color.Red)}
3 Modifikator-Kette Modifier.styleable{ contentColor(Color.Red) für die Komponente selbst.
4 (Niedrigste) Übergeordnete Stile Für Eigenschaften, die vom übergeordneten Element übernommen werden können (Typografie/Farbe).

Übergeordnetes Styling

Sie können Texteigenschaften wie contentColor im übergeordneten Composable festlegen. Sie werden dann 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. Übernahme von Eigenschaften durch untergeordnete Composables.

Überschreiben von Properties durch untergeordnete Properties

Sie können das Styling auch für eine bestimmte Text-Composable festlegen. Wenn für die übergeordnete zusammensetzbare Funktion ein Stil festgelegt ist, wird dieser durch den Stil der untergeordneten zusammensetzbaren Funktion überschrieben.

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 Eigenschaften.

Benutzerdefinierte Stileigenschaften implementieren

Sie können benutzerdefinierte Eigenschaften 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)
}

So wenden Sie diese neue Property in einer Stildefinition an:

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

Das Erstellen neuer formatierbarer Properties wird nicht unterstützt. Wenn Ihr Anwendungsfall eine solche Unterstützung erfordert, senden Sie einen Feature Request.

CompositionLocal-Werte lesen

Es ist ein gängiges Muster, Designsystem-Tokens in einem CompositionLocal zu speichern, um auf die Variablen zuzugreifen, ohne sie als Parameter übergeben zu müssen. Stile können auf CompositionLocal zugreifen, um systemweite Werte innerhalb eines Stils abzurufen:

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