I want to align the red surface to the center of the page, how can i do that?
@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)
) {}
}
}
View:
Want this:
CodePudding user response:
If your blue view has a static size, just add Spacer
of the same size on the other side.
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Spacer(Modifier.width(100.dp))
Surface(
color = Color.Red,
modifier = Modifier.size(100.dp, 50.dp)
){}
Surface(
color = Color.Blue,
modifier = Modifier.size(100.dp, 50.dp)
) {}
}
If it is dynamically sized, you can use the blue view instead of Spacer
and apply Modifier.alpha(0)
- this will be less performant than creating a custom layout, but should be perfectly fine, unless your view has a really huge layout to measure.
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Surface(
color = Color.Blue,
modifier = Modifier.size(100.dp, 50.dp).alpha(0f)
) {}
Surface(
color = Color.Red,
modifier = Modifier.size(100.dp, 50.dp)
){}
Surface(
color = Color.Blue,
modifier = Modifier.size(100.dp, 50.dp)
) {}
}
CodePudding user response:
You could just use a Layout
if things need to be precisely positioned.
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
)
}
}
}
That should just about do it, y'know provided that both Red AND Blue are of the same width. If not, you'll have to store the measurables' measure results in a variable instead of just using apply
. But that is no hard job -- It's actually super easy, barely an inconvenience.
EXPLANATION:
We call a simple Layout
Composable and pass our desired Composables to its content
block, since those are what we have to position. Then, we are given access to those same composables in the form of measurables
, which we can use to measure and place wherever we want. We also have a constraints
parameter which are just like the dimensions of the screen in this case. We return a layout
block, which is essentially a container for all the desired Composables, and we specify a width and a height, in this case max values for both of these dimensions, which corresponds to full screen here.
measurables
is an array containing all the Composables in order they were passed to the content
block. Hence, measurables[0]
is the Red
block and blue is on index 1. Now, we position the red block at precisely the center of the screen. Try tweaking the x and y values for a bit to see how the UI reacts. Afterwards we place Blue at an x
equal to the x
of Red
Width
of Red
(or blue, since they're the same here). We do this since we wish for blue to be placed exactly after Red
. x
is the distance from the edge of screen to the start (or left edge) of the Composable while y
is from its top.
CodePudding user response:
You can use the Layout
composable.
Something like:
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)
}
}
with:
internal fun widthOrZero(placeable: Placeable?) = placeable?.width ?: 0
internal fun heightOrZero(placeable: Placeable?) = placeable?.height ?: 0