Es gibt Auftauchen composable in Jetpack Compose, das a darstellt Materialoberfläche. Eine Oberfläche ermöglicht es Ihnen, Dinge wie Hintergrundfarbe oder Rahmen einzurichten, aber es scheint, dass das Gleiche mit der Verwendung möglich ist Modifikatoren. Wann sollte ich das Surface Composable verwenden und welche Vorteile bietet es mir?
Wann sollte ich Android Jetpack Compose Surface Composable verwenden?
Walerij Katkow
Auftauchen composable macht den Code einfacher und zeigt explizit an, dass der Code a verwendet Materialoberfläche. Sehen wir uns ein Beispiel an:
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)
)
}
und das Ergebnis:
Dasselbe Ergebnis kann ohne Surface erzielt werden:
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)
)
hat aber ein paar nachteile:
- Die Modifikatorkette ist ziemlich groß und es ist nicht offensichtlich, dass sie eine Materialoberfläche implementiert
- Ich muss eine Variable für die Form deklarieren und sie an drei verschiedene Modifikatoren übergeben
- Es verwendet contentColorFor um die Inhaltsfarbe herauszufinden, während Surface dies unter der Haube erledigt. Als Ergebnis die
backgroundColor
wird auch an zwei Stellen verwendet. - Ich muss die Höhe in Pixel berechnen
Surface
passt Farben für die Höhe an (im Falle eines dunklen Themas) nach Materialdesign. Wenn Sie das gleiche Verhalten wünschen, sollte es manuell gehandhabt werden.
Für die vollständige Liste der Surface-Funktionen werfen Sie am besten einen Blick auf die Dokumentation.
-
Das Blockieren der Berührungsausbreitung könnte vielleicht die wichtigste Rolle des Surface im Vergleich zu anderen Inhaltsansichten/Composables sein.
– Anm
13. September 2021 um 14:44 Uhr
Oberfläche ist das Äquivalent von CardView
im Sichtsystem.
Durch Surface
können Sie die Höhe für die Ansicht festlegen (beachten Sie, dass dies bei Modifier.shadow nicht dasselbe ist).
Thrakisch
Surface
ist ein Box
mit einer Modifier.surface()
und Materialfarben und Höhe, es überprüft die Höhe der Vorfahren, um immer über ihnen zu sein, und überlastet nur unten, um die Berührungsausbreitung hinter der Oberfläche zu blockieren 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()
}
}
}
Und 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)
Eine andere interessante Sache ist es Box
mit propagateMinConstraints = true
Parameter, der den ersten Nachkommen dazu zwingt, dieselben Mindestbeschränkungen oder -abmessungen zu haben
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))
) {
Box(
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))
) {
Box(
modifier = Modifier
.size(50.dp)
.background(Color.Green, RoundedCornerShape(6.dp))
)
}
}
Im ersten Beispiel auf Surface
Kräfte Column
haben 200.dp Größe, obwohl es hat Modifier.size(50.dp)
.
Im zweiten Beispiel Box
Innerhalb Column
hat eine Größe von 50.dp, weil es kein direkter Nachkomme von ist Surface
.
Im dritten Beispiel ersetzen wir Surface
(Box mit propagateMinConstraints true) mit Box
es erlaubt direkten Nachkommen, ihre eigenen Beschränkungen oder Dimensionen zu verwenden.