您可以通过以下三种方式在整个应用中采用样式:
- 直接用于公开
Style参数的现有组件。 - 对不接受
Style参数的布局可组合项应用Modifier.styleable样式。 - 在您自己的自定义设计系统中,使用
Modifier.styleable{}并为自己的组件公开样式参数。
样式中的可用属性
样式支持许多与修饰符相同的属性;不过,并非所有修饰符都可以通过样式进行复制。您仍然需要修饰符来实现某些行为,例如互动、自定义绘制或堆叠属性。
| 分组 | 属性 | 由子级继承 |
|---|---|---|
| 布局和尺寸调整 | ||
| 内边距 | contentPadding(内部)和 externalPadding(外部)。提供定向、水平、垂直和全方位变体。 |
否 |
| 尺寸 | fillWidth/Height/Size() 和 width、height 和 size(支持 Dp、DpSize 或 Float 分数)。 |
否 |
| Positioning | left/top/right/bottom 偏移量。 |
否 |
| 视觉外观 | ||
| 充满电 | background 和 foreground(支持 Color 或 Brush)。 |
否 |
| 边框 | borderWidth、borderColor 和 borderBrush。 |
否 |
| 形状 | shape |
否 - 但会与其他属性结合使用。clip 和 border 使用此定义的形状。 |
| 阴影 | dropShadow、innerShadow |
否 |
| 变换 | ||
| 图形层空间移动 | translationX、translationY、scaleX/Y、rotationX/Y/Z |
否 |
| 控制 | alpha、zIndex(堆叠顺序)和 transformOrigin(透视点) |
否 |
| 排版 | ||
| 样式 | textStyle、fontSize、fontWeight、fontStyle和fontFamily |
是 |
| 着色 | contentColor 和 contentBrush。这也用于图标样式设置。 |
是 |
| 段落 | lineHeight、letterSpacing、textAlign、textDirection、lineBreak 和 hyphens。 |
是 |
| 装饰 | textDecoration、textIndent 和 baselineShift。 |
是 |
使用样式参数直接在组件上使用样式
公开 Style 参数的组件允许您设置其样式:
BaseButton( onClick = { }, style = { } ) { BaseText("Click me") }
在样式 lambda 中,您可以设置各种属性,例如 externalPadding 或 background:
BaseButton( onClick = { }, style = { background(Color.Blue) } ) { BaseText("Click me") }
如需查看受支持属性的完整列表,请参阅样式中的可用属性。
使用修饰符为没有现有参数的组件应用样式
对于缺少内置样式参数的组件,您仍然可以使用 styleable 修饰符应用样式。在开发自己的自定义组件时,此方法也很有用。
Row( modifier = Modifier.styleable { } ) { BaseText("Content") }
与 style 参数类似,您可以在 lambda 内添加 background 或 padding 等属性。
Row( modifier = Modifier.styleable { background(Color.Blue) } ) { BaseText("Content") }
多个链接的 Modifier.styleable 修饰符会与所应用的可组合项上的非继承属性相加,其行为类似于定义相同属性的多个修饰符。对于继承的属性,这些属性会被覆盖,并且链中的最后一个 styleable 修饰符会设置相应的值。
使用 Modifier.styleable 时,您可能还需要创建并提供 StyleState,以便与修饰符搭配使用来应用基于状态的样式。如需了解详情,请参阅使用样式设置状态和动画。
定义独立样式
您可以定义一个独立的样式以供重复使用:
val style = Style { background(Color.Blue) }
然后,您可以将定义的样式传递到可组合项的样式参数中,也可以通过 Modifier.styleable 传递。使用 Modifier.styleable 时,您还需要创建一个 StyleState 对象。StyleState 在使用样式设置状态和动画文档中进行了详细介绍。
以下示例展示了如何通过组件的内置参数或通过 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") }
您还可以将该样式传递给多个组件:
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") }
添加多个样式属性
您可以通过在每行中设置不同的属性来添加多个样式属性:
BaseButton( onClick = { }, style = { background(Color.Blue) contentPaddingStart(16.dp) } ) { BaseText("Button") }
与基于修饰符的样式设置不同,样式中的属性不是累加的。样式会采用一个样式块中属性列表中的最后一个设置值。在以下示例中,背景设置了两次,TealColor 是应用的背景。对于内边距,contentPaddingTop 会替换 contentPadding 设置的上内边距,而不会合并这些值。
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!") }
contentPadding 替换的按钮。合并多个样式对象
您可以创建多个 Style 对象,并将它们传递到可组合函数的 style 参数中。
val style1 = Style { background(TealColor) } val style2 = Style { contentPaddingTop(16.dp) } BaseButton( style = style1 then style2, onClick = { }, ) { BaseText("Click me!") }
contentPaddingTop 的按钮。如果多个样式指定了同一属性,则选择最后设置的属性。由于样式中的属性不是累加的,因此传入的最后一个边衬区会替换初始 contentPadding 设置的 contentPaddingHorizontal。此外,最后一个背景颜色会覆盖传入的初始样式设置的背景颜色。
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!") }
在这种情况下,应用的样式具有浅灰色背景和 32.dp 内边距,但左侧和右侧内边距的值为 8.dp。
contentPadding 的按钮,该属性会被不同的样式替换。样式继承
某些样式属性(例如 contentColor 和与文本样式相关的属性)会传播到子可组合项。为子可组合项设置的样式会覆盖该特定子可组合项的继承父样式。
Style、styleable 和直接参数进行样式传播。| 优先级 | 方法 | 影响 |
|---|---|---|
| 1(最高) | 可组合项上的直接实参 | 替换所有内容;例如,Text(color = Color.Red) |
| 2 | 样式参数 | 本地样式覆盖 Text(style = Style { contentColor(Color.Red)} |
| 3 | 修饰符链 | Modifier.styleable{ contentColor(Color.Red)。 |
| 4(最低) | 父级样式 | 对于可从父级继承的属性(排版/颜色),从父级传递下来。 |
父级样式
您可以从父可组合函数设置文本属性(例如 contentColor),这些属性会传播到所有子 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") }
子级对属性的替换
您还可以为特定 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 can ", style = { contentBrush(Brush.linearGradient(listOf(Color.Red, Color.Blue))) }) BaseText("override properties") BaseText("set by their parents") }
实现自定义样式属性
您可以使用 StyleScope 的扩展函数创建映射到现有样式定义的自定义属性,如以下示例所示:
fun StyleScope.outlinedBackground(color: Color) { border(1.dp, color) background(color) }
在样式定义中应用此新属性:
val customExtensionStyle = Style { outlinedBackground(Color.Blue) }
不支持创建新的可设置样式的属性。如果您的使用情形需要此类支持,请提交功能请求。
读取 CompositionLocal 值
一种常见模式是将设计系统令牌存储在 CompositionLocal 中,以便在无需将变量作为参数传递的情况下访问这些变量。样式可以访问 CompositionLocal 以检索样式中的全局系统值:
val buttonStyle = Style { contentPadding(12.dp) shape(RoundedCornerShape(50)) background(Brush.verticalGradient(LocalCustomColors.currentValue.background)) }