Podstawy stylów

Style możesz zastosować w aplikacji na 3 sposoby:

  1. Używaj bezpośrednio w przypadku istniejących komponentów, które udostępniają parametr Style.
  2. Stosowanie stylu za pomocą Modifier.styleable w komponentach kompozycyjnych układu, które nie akceptują parametru Style.
  3. W własnym systemie projektowania niestandardowego użyj Modifier.styleable{} i udostępnij parametr stylu we własnych komponentach.

Dostępne właściwości w przypadku stylów

Style obsługują wiele tych samych właściwości co modyfikatory, ale nie wszystko, co jest modyfikatorem, można odtworzyć za pomocą stylu. Nadal potrzebujesz modyfikatorów w przypadku niektórych działań, takich jak interakcje, rysowanie niestandardowe czy układanie właściwości.

Grupowanie Właściwości Odziedziczone przez wydawców podrzędnych
Układ i rozmiar
Dopełnienie contentPadding (wewnętrzny) i externalPadding (zewnętrzny). Dostępne w wariantach kierunkowych, poziomych, pionowych i wszechstronnych. Nie
Wymiary fillWidth/Height/Size()width, heightsize (obsługuje ułamki Dp, DpSizeFloat). Nie
Pozycjonowanie left/top/right/bottom kompensacje. Nie
Wygląd
Ładowanie backgroundforeground (obsługuje Color lub Brush). Nie
Obramowanie borderWidth, borderColorborderBrush. Nie
Kształt shape Nie, ale jest używany w połączeniu z innymi właściwościami. clipborder używają tego zdefiniowanego kształtu.
Cienie dropShadow, innerShadow Nie
Transformacje
Przemieszczanie przestrzenne warstwy graficznej translationX, translationY, scaleX/Y, rotationX/Y/Z Nie
Kontrola alpha, zIndex (kolejność nakładania) i transformOrigin (punkt obrotu) Nie
Typografia
Stylizacja textStyle, fontSize, fontWeight, fontStylefontFamily Tak
Kolorystyka contentColorcontentBrush. Jest on też używany do stylizowania ikon. Tak
Akapit lineHeight, letterSpacing, textAlign, textDirection, lineBreakhyphens. Tak
Dekoracja textDecoration, textIndentbaselineShift. Tak

Używanie stylów bezpośrednio w komponentach za pomocą parametrów stylu

Komponenty, które udostępniają parametr Style, umożliwiają ustawienie stylu:

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

W funkcji lambda stylu możesz ustawić różne właściwości, np. externalPadding lub background:

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

Pełną listę obsługiwanych właściwości znajdziesz w artykule Dostępne właściwości w sekcji Style.

Stosowanie stylów za pomocą modyfikatorów w przypadku komponentów bez istniejącego parametru

W przypadku komponentów, które nie mają wbudowanego parametru stylu, możesz nadal stosować style za pomocą modyfikatora styleable. To podejście jest też przydatne podczas tworzenia własnych komponentów niestandardowych.

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

Podobnie jak w przypadku parametru style, w funkcji lambda możesz uwzględnić właściwości takie jak background czy padding.

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

Wiele połączonych modyfikatorów Modifier.styleable jest dodawanych do właściwości nieprzekazywanych w zastosowanym komponencie, co działa podobnie jak wiele modyfikatorów definiujących te same właściwości. W przypadku właściwości dziedziczonych są one zastępowane, a wartości ustawia ostatni modyfikator styleable w łańcuchu.

Gdy używasz Modifier.styleable, możesz też utworzyć i dostarczyć StyleState, który będzie używany z modyfikatorem do stosowania stylów opartych na stanie. Więcej informacji znajdziesz w artykule Stany i animacje w stylach.

Definiowanie samodzielnego stylu

Możesz zdefiniować samodzielny styl, aby można go było używać wielokrotnie:

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

Następnie możesz przekazać zdefiniowany styl do parametru stylu komponentu lub za pomocą Modifier.styleable. Jeśli używasz Modifier.styleable, musisz też utworzyć obiekt StyleState. StyleState jest szczegółowo omówiony w dokumentacji Stany i animacje ze stylami.

Poniższy przykład pokazuje, jak zastosować styl bezpośrednio za pomocą wbudowanych parametrów komponentu lub za pomocą elementu 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")
}

Możesz też przekazać ten styl do wielu komponentów:

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

Dodawanie wielu właściwości stylu

Możesz dodać wiele właściwości stylu, ustawiając różne właściwości w każdym wierszu:

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

Właściwości w stylach nie sumują się, w przeciwieństwie do stylów opartych na modyfikatorach. Style przyjmują ostatnią ustawioną wartość na liście właściwości w jednym bloku stylu. W poniższym przykładzie, w którym tło jest ustawione 2 razy, zastosowane tło to TealColor. W przypadku dopełnienia atrybut contentPaddingTop zastępuje dopełnienie górne ustawione przez atrybut contentPadding i nie łączy wartości.

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

Przycisk z ustawionymi 2 kolorami tła i 2 zastąpieniami contentPadding
Rysunek 1. Przycisk z ustawionymi 2 kolorami tła i 2 contentPaddingzastąpieniami
.

Scalanie wielu obiektów stylu

Możesz utworzyć wiele obiektów Style i przekazać je do parametru style w funkcji kompozycyjnej.

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

BaseButton(
    style = style1 then style2,
    onClick = {

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

Przycisk z kolorem tła i ustawionym parametrem contentPaddingTop
Rysunek 2. Przycisk z ustawionym kolorem tła i wartością contentPaddingTop.

Jeśli kilka stylów określa tę samą właściwość, wybierana jest ostatnia ustawiona właściwość. W przypadku stylów właściwości nie są sumowane, więc ostatni przekazany dopełnienie zastępuje contentPaddingHorizontal ustawione przez początkowy contentPadding. Dodatkowo ostatni kolor tła zastępuje kolor tła ustawiony przez początkowy styl przekazany w parametrze.

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

W tym przypadku zastosowany styl ma jasnoszare tło i 32.dp dopełnienie, z wyjątkiem dopełnienia po lewej i prawej stronie, które ma wartość 8.dp.

Przycisk z parametrem contentPadding, który jest zastępowany przez różne style
Rysunek 3. Przycisk z ikoną contentPadding, który jest zastępowany przez różne style.

Dziedziczenie stylu

Niektóre właściwości stylu, takie jak contentColor i właściwości związane ze stylem tekstu, są przekazywane do funkcji kompozycyjnych podrzędnych. Styl ustawiony w kompozycji podrzędnej zastępuje odziedziczony styl nadrzędny w przypadku tej konkretnej kompozycji podrzędnej.

Przekazywanie stylu za pomocą parametrów Style, styleable i direct
Rysunek 4. Propagowanie stylu za pomocą parametrów Style, styleable i bezpośrednich.
Priorytet Metoda Efekt
1 (najwyższy) Argumenty bezpośrednie w funkcji kompozycyjnej Zastępuje wszystko, np. Text(color = Color.Red)
2 Parametr stylu Zastąpienia stylu lokalnego Text(style = Style { contentColor(Color.Red)}
3 Łańcuch modyfikatorów Modifier.styleable{ contentColor(Color.Red) na samym komponencie.
4 (najniższy) Style nadrzędne W przypadku właściwości, które mogą być dziedziczone (typografia/kolor) przekazywanych z elementu nadrzędnego.

Styl nadrzędny

Właściwości tekstu (np. contentColor) możesz ustawić w funkcji kompozycyjnej nadrzędnej, a zostaną one przekazane do wszystkich funkcji kompozycyjnych podrzędnych Text.

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

Dziedziczenie właściwości komponentów podrzędnych
Rysunek 5. dziedziczenie właściwości komponentów podrzędnych;

Zastępowanie właściwości w usłudze podrzędnej

Możesz też ustawić styl dla konkretnego komponentu Text. Jeśli element kompozycyjny nadrzędny ma ustawiony styl, styl ustawiony w elemencie kompozycyjnym podrzędnym zastępuje styl elementu kompozycyjnego nadrzędnego.

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

Komponenty podrzędne zastępują właściwości komponentów nadrzędnych
Rysunek 6. Komponenty kompozycyjne podrzędne zastępują właściwości nadrzędne.

Wdrażanie niestandardowych właściwości stylu

Możesz tworzyć właściwości niestandardowe, które są mapowane na istniejące definicje stylu, używając funkcji rozszerzeń w StyleScope, jak pokazano w tym przykładzie:

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

Zastosuj tę nową właściwość w definicji stylu:

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

Tworzenie nowych właściwości, które można dostosowywać, jest niedostępne. Jeśli Twój przypadek użycia wymaga takiej obsługi, prześlij prośbę o dodanie funkcji.

Odczytywanie wartości CompositionLocal

Często stosuje się wzorzec przechowywania tokenów systemu projektowania w obiekcie CompositionLocal, aby uzyskać dostęp do zmiennych bez konieczności przekazywania ich jako parametrów. Style mogą uzyskiwać dostęp do CompositionLocal, aby pobierać wartości systemowe w ramach stylu:

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