Concetti fondamentali degli stili

Esistono tre modi per adottare gli stili in tutta l'app:

  1. Utilizzalo direttamente sui componenti esistenti che espongono un parametro Style.
  2. Applica uno stile con Modifier.styleable ai composable del layout che non accettano un parametro Style.
  3. Nel tuo sistema di progettazione personalizzato, utilizza Modifier.styleable{} ed esponi un parametro di stile sui tuoi componenti.

Proprietà disponibili negli stili

Gli stili supportano molte delle stesse proprietà supportate dai modificatori, ma non tutto ciò che è un modificatore può essere replicato con uno stile. Hai comunque bisogno di modificatori per determinati comportamenti, come interazioni, disegni personalizzati o impilamento delle proprietà.

Raggruppamento Proprietà Ereditato dai figli
Layout e dimensionamento
Spaziatura interna contentPadding (interna) e externalPadding (esterna). Disponibili nelle varianti direzionale, orizzontale, verticale e su tutti i lati. No
Dimensioni fillWidth/Height/Size() e width, height e size (supporta frazioni Dp, DpSize o Float). No
Presentazione left/top/right/bottom compensazioni. No
Aspetto visivo
Riempimento background e foreground (supporta Color o Brush). No
Bordi borderWidth, borderColor e borderBrush. No
Forma shape No, ma viene utilizzato in combinazione con altre proprietà. clip e border utilizzano questa forma definita.
Shadows dropShadow, innerShadow No
Trasformazioni
Movimento spaziale del livello di grafica translationX, translationY, scaleX/Y, rotationX/Y/Z No
Controllo alpha, zIndex (ordine di sovrapposizione) e transformOrigin (punto di rotazione) No
Tipografia
Stile textStyle, fontSize, fontWeight, fontStyle e fontFamily
Colorazione contentColor e contentBrush. Viene utilizzato anche per lo stile delle icone.
Paragrafo lineHeight, letterSpacing, textAlign, textDirection, lineBreak e hyphens.
Decorazione textDecoration, textIndent e baselineShift.

Utilizzare gli stili direttamente sui componenti con i parametri di stile

I componenti che espongono un parametro Style consentono di impostarne lo stile:

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

All'interno della lambda di stile, puoi impostare varie proprietà, ad esempio externalPadding o background:

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

Per l'elenco completo delle proprietà supportate, consulta Proprietà disponibili negli stili.

Applica stili utilizzando modificatori per i componenti senza parametri esistenti

Per i componenti che non dispongono di un parametro di stile integrato, puoi comunque applicare gli stili con il modificatore styleable. Questo approccio è utile anche per sviluppare componenti personalizzati.

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

Analogamente al parametro style, puoi includere proprietà come background o padding all'interno di lambda.

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

Più modificatori Modifier.styleable concatenati sono additivi con le proprietà non ereditate nel composable applicato, comportandosi in modo simile a più modificatori che definiscono le stesse proprietà. Per le proprietà ereditate, questi vengono sostituiti e l'ultimo modificatore styleable nella catena imposta i valori.

Quando utilizzi Modifier.styleable, potresti anche voler creare e fornire un StyleState da utilizzare con il modificatore per applicare uno stile basato sullo stato. Per maggiori dettagli, consulta Stato e animazioni con gli stili.

Definire uno stile autonomo

Puoi definire uno stile autonomo per riutilizzarlo:

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

Puoi quindi passare lo stile definito al parametro di stile di un elemento composable o con Modifier.styleable. Quando utilizzi Modifier.styleable, devi anche creare un oggetto StyleState. StyleState è trattato in dettaglio nella documentazione Stati e animazioni con gli stili.

Il seguente esempio mostra come applicare uno stile direttamente tramite i parametri integrati di un componente o tramite 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")
}

Puoi anche passare questo stile a più componenti:

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

Aggiungere più proprietà di stile

Puoi aggiungere più proprietà di stile impostando proprietà diverse su ogni riga:

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

Le proprietà in Stili non sono additive, a differenza dello stile basato sui modificatori. Gli stili prendono l'ultimo valore impostato nell'elenco delle proprietà all'interno di un blocco di stile. Nell'esempio seguente, con lo sfondo impostato due volte, TealColor è lo sfondo applicato. Per il padding, contentPaddingTop sostituisce il padding superiore impostato da contentPadding e non combina i valori.

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

Pulsante con due colori di sfondo impostati e due override di contentPadding
Figura 1. Pulsante con due colori di sfondo impostati e due contentPadding override.

Unire più oggetti di stile

Puoi creare più oggetti Style e passarli al parametro style del tuo composable.

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

BaseButton(
    style = style1 then style2,
    onClick = {

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

Pulsante con colore di sfondo e contentPaddingTop
impostato
Figura 2. Pulsante con colore di sfondo e contentPaddingTop impostati.

Quando più stili specificano la stessa proprietà, viene scelta l'ultima proprietà impostata. Poiché le proprietà non sono additive negli stili, l'ultimo padding passato sostituisce contentPaddingHorizontal impostato da contentPadding iniziale. Inoltre, l'ultimo colore di sfondo sostituisce il colore di sfondo impostato dallo stile iniziale passato.

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 questo caso, lo stile applicato ha uno sfondo grigio chiaro e un padding di 32.dp, ad eccezione del padding sinistro e destro, che ha un valore di 8.dp.

Pulsante con contentPadding sostituito da stili diversi
Figura 3. Pulsante con contentPadding sostituito da stili diversi.

Ereditarietà dello stile

Alcune proprietà di stile, come contentColor e quelle relative allo stile del testo, vengono propagate ai componenti componibili secondari. Uno stile impostato su un componente componibile secondario sostituisce lo stile principale ereditato per quel componente secondario specifico.

Propagazione dello stile con i parametri Style, styleable e direct
Figura 4. Propagazione dello stile con Style, styleable e parametri diretti.
Priorità Metodo Effetto
1 (più alta) Argomenti diretti su un elemento componibile Esegue l'override di tutto. Ad esempio, Text(color = Color.Red)
2 Parametro di stile Override di stile locali Text(style = Style { contentColor(Color.Red)}
3 Catena di modificatori Modifier.styleable{ contentColor(Color.Red) sul componente stesso.
4 (minimo) Stili principali Per le proprietà che possono essere ereditate (tipografia/colore) trasmesse dal genitore.

Stile principale

Puoi impostare le proprietà del testo (ad esempio contentColor) dal composable principale, e queste vengono propagate a tutti i composable Text secondari.

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

Ereditarietà delle proprietà dei composable secondari
Figura 5. Ereditarietà delle proprietà dei composable secondari.

Override delle proprietà secondarie

Puoi anche impostare lo stile di un composable Text specifico. Se il componibile principale ha uno stile impostato, lo stile impostato sul componibile secondario sostituisce lo stile del componibile principale.

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

I composable secondari sostituiscono le proprietà
principali
Figura 6. I composable secondari sostituiscono le proprietà principali.

Implementare proprietà di stile personalizzate

Puoi creare proprietà personalizzate che vengono mappate alle definizioni di stile esistenti utilizzando le funzioni di estensione in StyleScope, come mostrato nell'esempio seguente:

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

Applica questa nuova proprietà all'interno di una definizione di stile:

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

La creazione di nuove proprietà con stili personalizzabili non è supportata. Se il tuo caso d'uso richiede questo supporto, invia una richiesta di funzionalità.

Leggi i valori di CompositionLocal

È una pratica comune archiviare i token del sistema di progettazione all'interno di un CompositionLocal, per accedere alle variabili senza doverle passare come parametri. Gli stili possono accedere a CompositionLocal per recuperare valori a livello di sistema all'interno di uno stile:

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