Auf dieser Seite werden Best Practices für die Arbeit mit Stilen beschrieben, die für Konsistenz in Ihrer Codebasis sorgen. Außerdem werden die Prinzipien erläutert, die wir beim Entwerfen der APIs befolgt haben.
Richtig
Wir empfehlen folgende Best Practices:
Do: Use Styles for visuals and modifiers for behaviors (Do: Use Styles for visuals and modifiers for behaviors)
Verwenden Sie die Styles API für die visuelle Konfiguration (Hintergründe, Abstand, Rahmen) und reservieren Sie Modifikatoren für Verhaltensweisen wie Klicklogik, Gestenerkennung oder Barrierefreiheit.
Do: Expose Style parameters in design systems
Für Ihre eigenen benutzerdefinierten Designsystemkomponenten sollten Sie nach dem Modifier-Parameter ein Style-Objekt bereitstellen.
@Composable fun GradientButton( modifier: Modifier = Modifier, // ✅ DO: for design system components, expose a style modifier to consumers to be able to customize the components style: Style = Style ) { // Consume the style }
Do: Replace visual-based parameters with a Style (Empfehlung: Visuelle Parameter durch einen Stil ersetzen)
Erwägen Sie, Parameter in Ihren Composables durch einen einzelnen Style-Parameter zu ersetzen.
Beispiel:
// Before @Composable fun OldButton(background: Color, fontColor: Color) { } // After // ✅ DO: Replace visual-based parameters with a style that includes same properties @Composable fun NewButton(style: Style = Style) { }
Do: Prioritize Styles for animations
Verwenden Sie den integrierten animate-Block für zustandsbasiertes Styling mit Animationen, um im Vergleich zu Modifizierern eine bessere Leistung zu erzielen.
Do: „Last-write-wins“-Strategie nutzen
Nutzen Sie den Umstand, dass style-Properties überschrieben und nicht gestapelt werden.
Damit können Sie Standardkomponentenränder oder -hintergründe überschreiben, ohne mehrere Parameter zu benötigen.
Zu vermeidende Vorgehensweise
Die folgenden Muster sind nicht empfehlenswert:
Nicht: Styles für Interaktionslogik verwenden
Versuchen Sie nicht, onClick oder die Erkennung von Gesten in einem Stil zu verarbeiten. Stile sind auf visuelle Konfigurationen basierend auf dem Status beschränkt. Sie sollten daher keine Geschäftslogik enthalten, sondern nur eine unterschiedliche visuelle Darstellung basierend auf dem Status.
Nicht: Standardstil als Standardparameter angeben
Stilparameter sollten immer mit style: Style = Style deklariert werden:
@Composable fun BadButton( modifier: Modifier = Modifier, // ❌ DON'T set a default style here as a parameter style: Style = Style { background(Color.Red) } ) { }
Wenn Sie einen „default“-Parameter einfügen möchten, führen Sie den eingehenden Parameterstil mit dem Standardstil zusammen:
@Composable fun GoodButton( modifier: Modifier = Modifier, // ✅ Do: always pass it as a Style, do not pass other defaults style: Style = Style ) { // ... val defaultStyle = Style { background(Color.Red) } // ✅ Do Combine defaults inside with incoming parameter Box(modifier = modifier.styleable(styleState, defaultStyle, style)) { // your logic } }
Nicht: Stilparameter für layoutbasierte Composables angeben
Sie können zwar jedem Composable einen Stil zuweisen, aber es wird nicht erwartet, dass Layout-basierte oder bildschirmbezogene Composables einen Stil akzeptieren. Aus Nutzersicht ist unklar, was ein Stil auf dieser Ebene bewirken würde. Stile sind für Komponenten und nicht unbedingt für Layouts konzipiert.
Nicht: Stile in „Composition“ erstellen
CompositionLocals werden an dem Punkt gelesen, an dem der Stil definiert wird, nicht an dem Punkt, an dem er verwendet wird. Wenn der Stil tatsächlich verwendet wird, kann sich der Status von CompositionLocal geändert haben, was zu einem ungenauen Stil führt.
// DON'T - Create styles in Composition that access composition locals in this way - this will likely lead to issues when style is used / accessed, as it would not get updated when the value changes. @Composable fun containerStyle(): Style { val background = MaterialTheme.colorScheme.background val onBackground = MaterialTheme.colorScheme.onBackground return Style { background(background) contentColor(onBackground) } } // Do: Instead, Create StyleScope extension functions for your subsystems to access themed composition Locals val StyleScope.colors: JetsnackColors get() = JetsnackTheme.LocalJetsnackTheme.currentValue.colors val StyleScope.typography: androidx.compose.material3.Typography get() = JetsnackTheme.LocalJetsnackTheme.currentValue.typography val StyleScope.shapes: Shapes get() = JetsnackTheme.LocalJetsnackTheme.currentValue.shapes // Access CompositionLocals val button = Style { background(colors.brandSecondary) shape(shapes.small) }
Empfehlung: Einen Stil für Änderungen am Subsystemwert erstellen
Wenn Sie beispielsweise zwischen dem dunklen und hellen Modus wechseln, fragen Sie vorhandene thematische Werte (über CompositionLocal) ab, um Style dynamisch zu ändern:
// Do: Use CompositionLocals or themed values to create a single style val buttonStyle = Style { background(colors.brandSecondary) shape(shapes.small) }
Do: Switch out whole Styles when the component fundamentally differs across theme definitions (Do: Switch out whole Styles when the component fundamentally differs across theme definitions)
Sie können ganze Stilobjekte auf Designebene austauschen, wenn es sich um grundlegend unterschiedliche Designs handelt.
Wenn Sie beispielsweise eine App erstellen, die für jedes Produkt/jede Seite oder jedes Angebot unterschiedliche Designs hat und viele Eigenschaften eines Stils unterschiedlich sind, ist es akzeptabel, ganze Stilgruppen auf Designebene auszutauschen.
// DO Switch out whole styles when many properties differ - if Product A and Product B are two white labelled apps that provide different Themes. val productBThemedButton = Style { shape(shapes.small) background(colors.brandSecondary) // other properties are fundamentally different } val productAThemedButton = Style { shape(shapes.large) background(colors.brand) // other properties are fundamentally different }