[英]When should I use Android Jetpack Compose Surface composable?
Surface composable 使代碼更容易,並明確表明代碼使用材質表面。 讓我們看一個例子:
Surface(
color = MaterialTheme.colors.primarySurface,
border = BorderStroke(1.dp, MaterialTheme.colors.secondary),
shape = RoundedCornerShape(8.dp),
elevation = 8.dp
) {
Text(
text = "example",
modifier = Modifier.padding(8.dp)
)
}
結果:
不用 Surface 也能得到同樣的結果:
val shape = RoundedCornerShape(8.dp)
val shadowElevationPx = with(LocalDensity.current) { 2.dp.toPx() }
val backgroundColor = MaterialTheme.colors.primarySurface
Text(
text = "example",
color = contentColorFor(backgroundColor),
modifier = Modifier
.graphicsLayer(shape = shape, shadowElevation = shadowElevationPx)
.background(backgroundColor, shape)
.border(1.dp, MaterialTheme.colors.secondary, shape)
.padding(8.dp)
)
但它有一些缺點:
backgroundColor
也用在兩個地方。Surface
根據材料設計調整 colors 的高度(在深色主題的情況下)。 如果您想要相同的行為,則應手動處理。有關 Surface 功能的完整列表,最好查看文檔。
Surface 相當於視圖系統中的CardView
。
通過Surface
,您可以設置視圖的高程(注意這與 Modifier.shadow 不同)
Surface
是一個帶有Modifier.surface()
和材質 colors 和高程的Box
,它檢查祖先的高程是否始終在它們之上,並且僅在使用pointerInput(Unit) {}
阻止表面后面的觸摸傳播時過載。
@Composable
fun Surface(
modifier: Modifier = Modifier,
shape: Shape = RectangleShape,
color: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(color),
border: BorderStroke? = null,
elevation: Dp = 0.dp,
content: @Composable () -> Unit
) {
val absoluteElevation = LocalAbsoluteElevation.current + elevation
CompositionLocalProvider(
LocalContentColor provides contentColor,
LocalAbsoluteElevation provides absoluteElevation
) {
Box(
modifier = modifier
.surface(
shape = shape,
backgroundColor = surfaceColorAtElevation(
color = color,
elevationOverlay = LocalElevationOverlay.current,
absoluteElevation = absoluteElevation
),
border = border,
elevation = elevation
)
.semantics(mergeDescendants = false) {}
.pointerInput(Unit) {},
propagateMinConstraints = true
) {
content()
}
}
}
和Modifier.surface()
private fun Modifier.surface(
shape: Shape,
backgroundColor: Color,
border: BorderStroke?,
elevation: Dp
) = this.shadow(elevation, shape, clip = false)
.then(if (border != null) Modifier.border(border, shape) else Modifier)
.background(color = backgroundColor, shape = shape)
.clip(shape)
另一件有趣的事是Box
帶有propagateMinConstraints = true
參數,它強制第一個后代具有相同的最小約束或尺寸
Surface(
modifier = Modifier.size(200.dp),
onClick = {}) {
Column(
modifier = Modifier
.size(50.dp)
.background(Color.Red, RoundedCornerShape(6.dp))
) {}
}
Spacer(modifier = Modifier.height(20.dp))
Surface(
modifier = Modifier.size(200.dp),
onClick = {}) {
Column(
modifier = Modifier
.size(50.dp)
.background(Color.Red, RoundedCornerShape(6.dp))
) {
Column(
modifier = Modifier
.size(50.dp)
.background(Color.Green, RoundedCornerShape(6.dp))
) {}
}
}
Spacer(modifier = Modifier.height(20.dp))
Box(
modifier = Modifier.size(200.dp)
) {
Column(
modifier = Modifier
.size(50.dp)
.background(Color.Red, RoundedCornerShape(6.dp))
) {
Column(
modifier = Modifier
.size(50.dp)
.background(Color.Green, RoundedCornerShape(6.dp))
) {}
}
}
在Surface
的第一個示例中,強制Column
具有200.dp大小,即使它具有Modifier.size(50.dp)
。
在第二個示例中, Box
inside Column
的大小為 50.dp,因為它不是Surface
的直接后代。
在第三個示例中,如果我們用Box
替換Surface
( Box 與propagateMinConstraints true ),它允許直接后代使用其自己的約束或尺寸。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.