Aspectos básicos de los estilos

Existen tres maneras de adoptar estilos en toda tu app:

  1. Usa directamente en los componentes existentes que exponen un Style parámetro.
  2. Aplica un estilo con Modifier.styleable en los elementos componibles de diseño que no aceptan un parámetro Style.
  3. En tu propio sistema de diseño personalizado, usa Modifier.styleable{} y expón un parámetro de estilo en tus propios componentes.

Propiedades disponibles en los estilos

Los estilos admiten muchas de las mismas propiedades que los modificadores. Sin embargo, no todo lo que es un modificador se puede replicar con un estilo. Aún necesitas modificadores para ciertos comportamientos, como interacciones, dibujos personalizados o apilamiento de propiedades.

Agrupación Propiedades Heredadas por los elementos secundarios
Diseño y tamaño
Padding del contenido (interno) - contentPadding(all: Dp)
- contentPadding(horizontal: Dp, vertical: Dp)
- contentPadding(start: Dp, top: Dp, end: Dp, bottom: Dp)
- contentPaddingHorizontal(value: Dp) / contentPaddingVertical(value: Dp)
- contentPaddingStart(value: Dp) / contentPaddingTop(value: Dp) / contentPaddingEnd(value: Dp) / contentPaddingBottom(value: Dp)
No
Padding externo (externo) - externalPadding(all: Dp)
- externalPadding(horizontal: Dp, vertical: Dp)
- externalPadding(start: Dp, top: Dp, end: Dp, bottom: Dp)
- externalPaddingHorizontal(value: Dp) / externalPaddingVertical(value: Dp)
- externalPaddingStart(value: Dp) / externalPaddingTop(value: Dp) / externalPaddingEnd(value: Dp) / externalPaddingBottom(value: Dp)
No
Dimensiones fillWidth()/fillHeight()/fillSize() y width, height y size (admite fracciones Dp, DpSize o Float). No
Posicionamiento Desplazamientos left/top/right/bottom. No
Apariencia visual
Llena background y foreground (admite Color o Brush). No
Bordes borderWidth, borderColor y borderBrush. No
Forma shape No, pero se usa junto con otras propiedades. clip y border usan esta forma definida.
Sombras dropShadow, innerShadow No
Transformaciones
Movimiento espacial de la capa de gráficos translationX, translationY, scaleX/scaleY, rotationX/rotationY/rotationZ No
Control alpha, zIndex (orden de apilamiento) y transformOrigin (punto de pivote) No
Tipografía
Diseño textStyle, fontSize, fontWeight, fontStyle y fontFamily
Coloración contentColor y contentBrush. También se usa para el diseño de íconos.
Párrafo lineHeight, letterSpacing, textAlign, textDirection, lineBreak y hyphens.
Decoración textDecoration, textIndent y baselineShift.

Usa estilos directamente en componentes con parámetros de estilo

Los componentes que exponen un parámetro Style te permiten configurar su diseño:

BaseButton(
    onClick = { },
    style = { }
) {
    BaseText("Click mnippets.kt

Dentro de la lambda de estilo, puedes establecer varias propiedades, como externalPadding o background:

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

Para obtener la lista completa de las propiedades admitidas, consulta Propiedades disponibles en los estilos.

Aplica estilos con modificadores para componentes sin parámetros existentes

En el caso de los componentes que no tienen un parámetro de estilo integrado, puedes aplicar estilos con el modificador styleable. Este enfoque también es útil cuando desarrollas tus propios componentes personalizados.

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

De manera similar al parámetro style, puedes incluir propiedades como background, contentPadding o externalPadding dentro de la lambda.

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

Varios modificadores Modifier.styleable encadenados son aditivos con propiedades no heredadas en el elemento componible aplicado, y se comportan de manera similar a varios modificadores que definen las mismas propiedades. En el caso de las propiedades heredadas, se anulan, y el último modificador styleable de la cadena establece los valores.

Cuando usas Modifier.styleable, también es posible que desees crear y proporcionar un StyleState para usarlo con el modificador para aplicar un diseño basado en el estado. Para obtener más detalles, consulta Estado y animaciones con estilos.

Define un estilo independiente

Puedes definir un estilo independiente para fines de reutilización:

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

Luego, puedes pasar ese estilo definido al parámetro de estilo de un elemento componible o con Modifier.styleable. Cuando usas Modifier.styleable, también debes crear un objeto StyleState. StyleState se aborda en detalle en la documentación Estado y animaciones con estilos.

En el siguiente ejemplo, se muestra cómo puedes aplicar un estilo directamente a través de los parámetros integrados de un componente o a través de 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("Col)
}StylesSnippets.kt

También puedes pasar ese estilo a varios componentes:

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, stText("Row")
}StylesSnippets.kt

Agrega varias propiedades de estilo

Puedes agregar varias propiedades de estilo si configuras diferentes propiedades en cada línea:

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

Las propiedades de los estilos no son aditivas, a diferencia del diseño basado en modificadores. Los estilos toman el último valor establecido en la lista de propiedades dentro de un bloque de estilo. En el siguiente ejemplo, con el fondo configurado dos veces, TealColor es el fondo aplicado. Para el padding, contentPaddingTop anula el padding superior establecido por contentPadding y no combina los valores.

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 menippets.kt

Botón con dos colores de fondo establecidos y dos anulaciones de contentPadding
Figura 1. Botón con dos colores de fondo configurados y dos anulaciones de contentPadding.

Combina varios objetos de estilo

Puedes crear varios objetos de estilo y pasarlos al parámetro de estilo de tu elemento componible.

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

BaseButton(
    style = style1 then style2,
    onClick = {

    },
) {
    BaseText("Click menippets.kt

Botón con color de fondo y contentPaddingTop establecidos
Figura 2. Botón con color de fondo y contentPaddingTop configurados.

Cuando varios estilos especifican la misma propiedad, se elige la última propiedad establecida. Debido a que las propiedades no son aditivas en los estilos, el último padding pasado anula el contentPaddingHorizontal establecido por el inicial contentPadding. Además, el último color de fondo anula el color de fondo establecido por el estilo inicial pasado.

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 menippets.kt

En este caso, el diseño aplicado tiene un fondo gris claro y un padding de 32.dp, excepto el padding izquierdo y derecho, que tiene un valor de 8.dp.

Botón con contentPadding anulado por diferentes estilos
Figura 3. Botón con contentPadding que se anula con diferentes estilos.

Herencia de estilo

Ciertas propiedades de estilo, como contentColor y las propiedades relacionadas con el estilo de texto, se propagan a los elementos componibles secundarios. Un estilo establecido en un elemento componible secundario anula el diseño superior heredado para ese elemento secundario específico.

Propagación de estilo con parámetros de Style, styleable y direct
Figura 4. Propagación de estilo con parámetros Style, styleable y directos.
Prioridad Método Efecto
1 (más alta) Argumentos directos en un elemento componible Anula todo; por ejemplo, Text(color = Color.Red)
2 Parámetro de estilo Anulaciones de estilo local Text(style = Style { contentColor(Color.Red)}
3 Cadena de modificadores Modifier.styleable{ contentColor(Color.Red) en el componente.
4 (más baja) Estilos superiores Para las propiedades que se pueden heredar (tipografía/color) que se pasan del elemento superior.

Diseño superior

Puedes establecer propiedades de texto (como contentColor) desde el elemento componible superior, y se propagan a todos los elementos componibles Text secundarios.

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(&quents")
}StylesSnippets.kt

Herencia de propiedades de elementos componibles secundarios
Figura 5. Herencia de propiedades de elementos componibles secundarios.

Anulación de propiedades secundarias

También puedes configurar el diseño en un elemento componible Text específico. Si el elemento componible superior tiene un diseño establecido, el diseño establecido en el elemento componible secundario anula el diseño del elemento componible superior.

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("ents")
}StylesSnippets.kt

Los elementos componibles secundarios anulan las propiedades principales
Figura 6. Los elementos componibles secundarios anulan las propiedades superiores.

Implementa propiedades de estilo personalizadas

Puedes crear propiedades personalizadas que se asignen a definiciones de estilo existentes mediante el uso de funciones de extensión en StyleScope, como se muestra en el siguiente ejemplo:

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

Aplica esta nueva propiedad dentro de una definición de estilo:

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

No se admite la creación de nuevas propiedades de estilo. Si tu caso de uso requiere dicha compatibilidad, envía una solicitud de función.

Lee valores de CompositionLocal

Es un patrón común almacenar tokens del sistema de diseño dentro de un CompositionLocal para acceder a las variables sin necesidad de pasarlas como parámetros. Los estilos pueden acceder a CompositionLocal para recuperar valores en todo el sistema dentro de un estilo:

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