Reputation: 1061
I'm trying to overlap two Box
or perhaps is better to use Row
on this case.
My design is one Row
overlapped with another one, and I've wrapped it on a Column
, is that correct?
This is the design, what I'd like to have is the rectangle of the top be the same size of the one below and then move it some pixels as you can see in the image, but they should have the same width but not the same height.
Is it okay if the hierarchy is :
Column
Box (the one of the top)
Row
Box (the one of the bottom)
Row (inside there is text and it's all the same align)
......
Upvotes: 17
Views: 35128
Reputation: 1002
You can also use the offset like this below to achieve the image overlay effort like this.
Box(
modifier = Modifier
.wrapContentWidth()
.wrapContentHeight()
) {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(imageOne)
.crossfade(true)
.build(),
contentDescription = nameOne,
contentScale = ContentScale.Crop,
modifier = Modifier
.size(55.dp)
.clip(CircleShape)
.align(Alignment.Center)
)
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(imageTwo)
.crossfade(true)
.build(),
contentDescription = nameOne,
contentScale = ContentScale.Crop,
modifier = Modifier
.size(55.dp)
.offset(x = 5.dp, y = 5.dp)
.align(Alignment.Center)
.clip(CircleShape)
)
}
X = horizontal, Y = Vertical
Upvotes: 5
Reputation: 673
To have two boxes or any other composables overlap in this way you can use spacedBy
method for the arrangement, either on a Row
or Column
and pass a negative value. This is supported by the Android docs as well.
For example:
fun OverlappingBoxesPreview() {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(20.dp),
verticalArrangement = Arrangement.spacedBy((-30).dp),
) {
Box(
modifier = Modifier
.size(100.dp)
.background(Color.Red),
)
Box(
modifier = Modifier
.size(80.dp)
.background(Color.Green),
)
}
}
Will produce:
Upvotes: 6
Reputation: 35
I think you must use "matchParentSize" modifier that is avaliabele inside BoxScope, I mean inside Box composable, that modifer measure other children size except itself when it has join the composable at first time to apply the same size to itself.
you can see this modifier in documentation https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/BoxScope#(androidx.compose.ui.Modifier).matchParentSize()
Upvotes: 1
Reputation: 459
This is way using BoxWithConstraints and not using fixed width and height:
BoxWithConstraints(
Modifier
.background(color = Color.Blue)
.padding(20.dp)) {
val boxWidth = this.maxWidth
Box(
modifier = Modifier
.width(boxWidth - 10.dp)
.background(Color.Red)
) {
Text(text = "Hello Android")
}
Column() {
Spacer(modifier = Modifier
.height(10.dp)
.width(10.dp))
Row( ) {
Spacer(modifier = Modifier.width(10.dp))
Box(
modifier = Modifier
.width(boxWidth)
.zIndex(2f)
.background(Color.Yellow)
) {
Text("aa", modifier = Modifier.background(color = Color.Green))
}
}
}
}
Upvotes: 13
Reputation: 20646
I've faced with this some days ago and I solved it using ConstraintLayout
.
What I had to do is :
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-beta02"
to build.gradle
Box
in a ConstraintLayout { .. }
Box
add a Modifier.constrainAs
to align the Top
Bottom
Start
End
as you want.width
as the second one without hardcoding the dps
you should use width = Dimension.fillToConstraints
fillToConstraints - the layout will expand to fill the space defined by its constraints in that dimension.
Basic example without hard-coding :
ConstraintLayout() {
val (title, description) = createRefs()
Box(
modifier = Modifier
.padding(start = 28.dp)
.background(color = Red)
.padding(
horizontal = 16.dp,
)
.constrainAs(title) {
top.linkTo(parent.top)
start.linkTo(parent.start)
end.linkTo(parent.end)
width = Dimension.fillToConstraints
}
) {
Text(text = "Hello World")
}
Box(
modifier = Modifier
.padding(end = 4.dp)
.background(Color.Magenta)
.padding(bottom = 5.dp, start = 8.dp, end = 16.dp, top = 4.dp)
.constrainAs(description) {
top.linkTo(title.top, margin = 16.dp)
start.linkTo(parent.start)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
) {
Text(text = "Skizo-ozᴉʞS rules")
}
}
Now you have to play with the padding
according to your UI and adapt it, result is something like this :
Upvotes: 15
Reputation: 1465
You can achieve this in many ways,
@Composable
fun BoxOverBox() {
Box(
modifier = Modifier.fillMaxSize()
.background(Color.White),
contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.width(200.dp)
.height(50.dp)
.background(Color.Red)
)
Box(
modifier = Modifier
.width(200.dp)
.height(50.dp)
.zIndex(2f)
.graphicsLayer {
translationX = -50f
translationY = 50f
}
.background(Color.Blue)
)
}
}
Upvotes: 4
Reputation: 1265
In order for the Composables
to overlap, you should put them in the same Box
. Try this out:
Box(modifier = Modifier.size(width = 300.dp, height = 100.dp)) {
Row(modifier = Modifier
.size(width = 200.dp, height = 50.dp)
.background(color = Color.Blue)
.align(Alignment.TopEnd)) {}
Row(modifier = Modifier
.size(width = 200.dp, height = 70.dp)
.background(color = Color.Red)
.align(Alignment.BottomStart)) {}
}
Upvotes: 11