在 Jetpack Compose 中将两个有序组件的第一个组件居中对齐的最简单方法是什么?
What is the simplest way to align center on first component of two ordered component in jetpack compose?
我想将红色表面与页面中心对齐,我该怎么做?
@Composable
fun Screen() {
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Surface(
color = Color.Red,
modifier = Modifier.size(100.dp, 50.dp)
){}
Surface(
color = Color.Blue,
modifier = Modifier.size(100.dp, 50.dp)
) {}
}
}
查看:
想要这个:
如果需要精确定位,您可以只使用 Layout
。
Layout(
content = { Red(); Blue() } // Add Composables here
) { measurables, constraints ->
layout(width = constraints.maxWidth, height = constraints.maxHeight) {
measurables[0].measure(constraints).apply { //Red
place(
(constraints.maxWidth - width) / 2,
(constraints.maxHeight - height) / 2
)
}
measurables[1].measure(constraints).apply {
place(
(constraints.maxWidth + width) / 2,
(constraints.maxHeight - height) / 2
)
}
}
}
这应该差不多了,你知道的,前提是红色和蓝色的宽度相同。如果不是,则必须将可测量对象的测量结果存储在变量中,而不是仅使用 apply
。但这并不难——实际上非常简单,几乎没有什么不便。
解释:
我们调用一个简单的 Layout
可组合项并将我们想要的可组合项传递给它的 content
块,因为这些是我们必须定位的。然后,我们可以以 measurables
的形式访问这些相同的可组合项,我们可以使用它们来测量和放置我们想要的任何地方。我们还有一个 constraints
参数,在这种情况下就像屏幕的尺寸一样。我们 return 一个 layout
块,它本质上是所有所需可组合项的容器,我们指定宽度和高度,在本例中是这两个维度的最大值,对应于全屏这里。
measurables
是一个包含所有可组合项的数组,按顺序将它们传递到 content
块。因此,measurables[0]
是 Red
块,蓝色在索引 1 上。现在,我们将红色块精确定位在屏幕的中心。尝试稍微调整 x 和 y 值以查看 UI 的反应。之后,我们将蓝色置于 x
等于 Red
的 x
+ Red
的 Width
(或蓝色,因为它们在这里相同)。我们这样做是因为我们希望蓝色恰好放在 Red
之后。 x
是从屏幕边缘到可组合项开始(或左边缘)的距离,而 y
是从其顶部开始的距离。
您可以使用 Layout
可组合项。
类似于:
Layout( content = {
Surface(
color = Color.Red,
modifier = Modifier
.size(100.dp, 50.dp)
.layoutId("red")
) {}
Surface(
color = Color.Blue,
modifier = Modifier
.size(100.dp, 50.dp)
.layoutId("blue")
) {}
}){ measurables, incomingConstraints ->
val constraints = incomingConstraints.copy(minWidth = 0, minHeight = 0)
val redPlaceable =
measurables.find { it.layoutId == "red" }?.measure(constraints)
val bluePlaceable =
measurables.find { it.layoutId == "blue" }?.measure(constraints)
//align red and blue
layout(
width = constraints.maxWidth, constraints.maxHeight)
{
val redPositionx = (constraints.maxWidth - widthOrZero(redPlaceable)) /2
val redPositiony = (constraints.maxHeight - heightOrZero(redPlaceable)) /2
redPlaceable?.placeRelative(redPositionx, redPositiony)
bluePlaceable?.placeRelative(redPositionx+widthOrZero(redPlaceable), redPositiony)
}
}
与:
internal fun widthOrZero(placeable: Placeable?) = placeable?.width ?: 0
internal fun heightOrZero(placeable: Placeable?) = placeable?.height ?: 0
如果您的蓝色视图具有静态尺寸,只需在另一侧添加相同尺寸的 Spacer
。
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
val blueViewWidth = 100.dp
Spacer(Modifier.width(blueViewWidth))
RedView()
BlueView(Modifier.size(blueViewWidth, 50.dp))
}
如果蓝色视图大小取决于内容,您可以使用它代替 Spacer
并应用 Modifier.alpha(0)
- 这将比创建自定义布局性能低,但应该非常好,除非你的视图有一个非常大的布局来衡量。
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
BlueView(Modifier.alpha(0f))
RedView()
BlueView()
}
我想将红色表面与页面中心对齐,我该怎么做?
@Composable
fun Screen() {
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Surface(
color = Color.Red,
modifier = Modifier.size(100.dp, 50.dp)
){}
Surface(
color = Color.Blue,
modifier = Modifier.size(100.dp, 50.dp)
) {}
}
}
查看:
想要这个:
如果需要精确定位,您可以只使用 Layout
。
Layout(
content = { Red(); Blue() } // Add Composables here
) { measurables, constraints ->
layout(width = constraints.maxWidth, height = constraints.maxHeight) {
measurables[0].measure(constraints).apply { //Red
place(
(constraints.maxWidth - width) / 2,
(constraints.maxHeight - height) / 2
)
}
measurables[1].measure(constraints).apply {
place(
(constraints.maxWidth + width) / 2,
(constraints.maxHeight - height) / 2
)
}
}
}
这应该差不多了,你知道的,前提是红色和蓝色的宽度相同。如果不是,则必须将可测量对象的测量结果存储在变量中,而不是仅使用 apply
。但这并不难——实际上非常简单,几乎没有什么不便。
解释:
我们调用一个简单的 Layout
可组合项并将我们想要的可组合项传递给它的 content
块,因为这些是我们必须定位的。然后,我们可以以 measurables
的形式访问这些相同的可组合项,我们可以使用它们来测量和放置我们想要的任何地方。我们还有一个 constraints
参数,在这种情况下就像屏幕的尺寸一样。我们 return 一个 layout
块,它本质上是所有所需可组合项的容器,我们指定宽度和高度,在本例中是这两个维度的最大值,对应于全屏这里。
measurables
是一个包含所有可组合项的数组,按顺序将它们传递到 content
块。因此,measurables[0]
是 Red
块,蓝色在索引 1 上。现在,我们将红色块精确定位在屏幕的中心。尝试稍微调整 x 和 y 值以查看 UI 的反应。之后,我们将蓝色置于 x
等于 Red
的 x
+ Red
的 Width
(或蓝色,因为它们在这里相同)。我们这样做是因为我们希望蓝色恰好放在 Red
之后。 x
是从屏幕边缘到可组合项开始(或左边缘)的距离,而 y
是从其顶部开始的距离。
您可以使用 Layout
可组合项。
类似于:
Layout( content = {
Surface(
color = Color.Red,
modifier = Modifier
.size(100.dp, 50.dp)
.layoutId("red")
) {}
Surface(
color = Color.Blue,
modifier = Modifier
.size(100.dp, 50.dp)
.layoutId("blue")
) {}
}){ measurables, incomingConstraints ->
val constraints = incomingConstraints.copy(minWidth = 0, minHeight = 0)
val redPlaceable =
measurables.find { it.layoutId == "red" }?.measure(constraints)
val bluePlaceable =
measurables.find { it.layoutId == "blue" }?.measure(constraints)
//align red and blue
layout(
width = constraints.maxWidth, constraints.maxHeight)
{
val redPositionx = (constraints.maxWidth - widthOrZero(redPlaceable)) /2
val redPositiony = (constraints.maxHeight - heightOrZero(redPlaceable)) /2
redPlaceable?.placeRelative(redPositionx, redPositiony)
bluePlaceable?.placeRelative(redPositionx+widthOrZero(redPlaceable), redPositiony)
}
}
与:
internal fun widthOrZero(placeable: Placeable?) = placeable?.width ?: 0
internal fun heightOrZero(placeable: Placeable?) = placeable?.height ?: 0
如果您的蓝色视图具有静态尺寸,只需在另一侧添加相同尺寸的 Spacer
。
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
val blueViewWidth = 100.dp
Spacer(Modifier.width(blueViewWidth))
RedView()
BlueView(Modifier.size(blueViewWidth, 50.dp))
}
如果蓝色视图大小取决于内容,您可以使用它代替 Spacer
并应用 Modifier.alpha(0)
- 这将比创建自定义布局性能低,但应该非常好,除非你的视图有一个非常大的布局来衡量。
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
BlueView(Modifier.alpha(0f))
RedView()
BlueView()
}