簡體   English   中英

我什么時候應該使用 Android Jetpack Compose Surface 可組合?

[英]When should I use Android Jetpack Compose Surface composable?

Jetpack Compose 中有Surface composable ,它代表一個材質表面 表面允許您設置諸如背景顏色或邊框之類的東西,但似乎也可以使用 修飾符來完成。 我應該什么時候使用 Surface 可組合產品,它給我帶來了什么好處?

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

但它有一些缺點:

  • 修改器鏈非常大,它實現了材質表面並不明顯
  • 我必須為形狀聲明一個變量並將其傳遞給三個不同的修飾符
  • 它使用contentColorFor來計算內容顏色,而 Surface 在引擎蓋下進行。 因此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替換SurfaceBox 與propagateMinConstraints true ),它允許直接后代使用其自己的約束或尺寸。

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM