CompositionLocal
通常情况下,在 Compose 中,数据以参数形式向下流经整个界面树传递给每个可组合函数。但是,对于广泛使用的常用数据(如颜色或类型样式),这可能会很麻烦。

为了支持无需将颜色作为显式参数依赖项层层传递给大多数可组合项,Compose 提供了 CompositionLocal ,可让你创建以树为作用域的具名对象,这可以用作让数据流经界面树的一种隐式方式。
我们可以通过 MaterialTheme 的 colors、shapes 和 typography 属性访问的 LocalColors、LocalShapes 和 LocalTypography 属性。

这些属性都不需要层层往下传递,而是可以在任何一个组件中直接使用, 如下代码所示:

如需为 CompositionLocal 提供新值,请使用 CompositionLocalProvider 及其 providers infix 函数。
示例:有 4 个 Text,但是他们的透明度不一样


CompositionLocal 的 current 值对应于该组合部分中的某个祖先提供的最接近的值。
例如,上面代码中,第一个 Text() 最近的祖先是 MaterialTheme(),而在 MaterialTheme 中默认设置 LocalContentAlpha 为 1f。
而此时提供的 current 值就是 high = 1f

依次类推,第2、3个文本最近的祖先是我们设置的第一个 current ,即 medium = 0.74f;第4个文本最近的祖先是我们设置的第二个 current,即 disabled = 0.38f
自定义CompositionLocal
示例:有两个 Card ,分别设置不同 elevation(z 轴上的海拔) 属性。将 elevation 定义为自己的 CompositonLocal,即 LocalElevations。右边第一个 Mycard 的海拔比较高,而第二个 MyCard 的海拔较低。

- MyCard.kt
Kotlin
//TODO 自定义一个 CompositionLocal
data class Elevations(val card : Dp = 0.dp)
val LocalElevations = compositionLocalOf { Elevations() }
// 初始化一些预定值
object CardElevation{
val high : Elevations
get() = Elevations(card = 10.dp)
val middle : Elevations
get() = Elevations(card = 5.dp)
val low : Elevations
get() = Elevations(card = 1.dp)
}
@Composable
fun MyCard(
elevation : Dp = LocalElevations.current.card,
backgroundColor : Color,
content : @Composable () -> Unit
){
Card (
elevation = elevation, // 海拔,一种阴影效果
backgroundColor = backgroundColor,
content = content,
modifier = Modifier.size(200.dp)
)
}
- CompositionLocalSample.kt
Kotlin
@Composable
fun CompositionSample3(){
Column {
// TODO 使用自定义组件 MyCard, 自定义 Elevation 设置为 high = 10.dp
CompositionLocalProvider(LocalElevations.provides(CardElevation.high)) {
MyCard(
backgroundColor = MaterialTheme.colors.onSurface.copy(alpha = 0.05f),
) {
}
}
// TODO 使用自定义组件 MyCard, 自定义 Elevation 设置为 low = 2.dp
CompositionLocalProvider(LocalElevations provides CardElevation.low) {
MyCard(
backgroundColor = MaterialTheme.colors.onSurface.copy(alpha = 0.05f),
) {
}
}
}
}
- MainActivity.kt 里使用 CompositionLocalSample

Material Design
Material Design 是一个用于创建数字界面的综合设计体系, Material Design 组件(按钮、卡片、开关)建立在 Material Theming 之上,Material theme 包括颜色 、排版 和形状属性。
自定义主题