I have created a custom layout to create a hexagonal grid, however, when I place the grid with other elements, for example inside a Row or Column, the grid won't update its position and stays on the top left corner of the map.
Here is my code:
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.GenericShape
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import com.example.mygame.ui.theme.MyGameTheme
private val HexagonalShape = GenericShape { size, _ ->
moveTo(size.width / 2f, 0f)
lineTo(size.width, size.height / 4f)
lineTo(size.width, 3 * size.height / 4f)
lineTo(size.width / 2f, size.height)
lineTo(0f, 3 * size.height / 4f)
lineTo(0f, size.height / 4f)
}
@Composable
fun StandardTile(color: Color) {
Box(
modifier = Modifier
.padding(horizontal = 1.dp, vertical = 1.dp)
.wrapContentSize(Alignment.Center)
.size(50.dp)
.clip(HexagonalShape)
.background(color)
.clickable { /* TODO */ }
.border(
width = 1.dp,
brush = SolidColor(Color.Black),
shape = HexagonalShape
)
) { }
}
@Composable
fun Grid(
modifier: Modifier,
lineLength: Int,
content: @Composable () -> Unit
) {
Layout(
modifier = modifier,
content = content
) { measurables, constraints ->
val placeables = measurables.map { measurable ->
measurable.measure(constraints)
}
layout(constraints.maxWidth, constraints.maxHeight) {
var yPosition = 0
var xPosition = 0
val index = mutableListOf(0, 0)
placeables.forEach { placeable ->
placeable.placeRelative(x = xPosition, y = yPosition)
if (index[0] != lineLength - 1) {
index[0]++
xPosition += placeable.width
} else {
xPosition = if (index[1] % 2 == 0) placeable.width / 2 else 0
yPosition += 3 * placeable.height / 4
index[0] = 0
index[1]++
}
}
}
}
}
@Preview
@Composable
fun ShapePreview() {
MyGameTheme {
ConstraintLayout {
val (gridRef, leftMenu) = createRefs()
val margin = 0.10f
val leftConstraint = createGuidelineFromStart(fraction = margin)
val rightConstraint = createGuidelineFromEnd(fraction = margin)
Column(
modifier = Modifier
.constrainAs(gridRef) {
linkTo(start = rightConstraint, end = leftConstraint)
start.linkTo(rightConstraint)
}
.fillMaxWidth()) {
Grid(
modifier = Modifier,
lineLength = 8
) {
for (i in 1..64) {
StandardTile(Color.Blue)
}
}
}
val leftMenuScrollState = rememberScrollState()
Column(
modifier = Modifier
.constrainAs(leftMenu) {
linkTo(start = parent.start, end = leftConstraint)
start.linkTo(parent.start)
}
.background(Color.Black)
.fillMaxWidth(fraction = margin)
.fillMaxHeight()
.verticalScroll(leftMenuScrollState)
) {
Text("Help Please, (this is inside the left menu btw)")
}
}
}
}
As you can see that I am using a ConstraintLayout. The relative position of the grid won't change and I don't know why, and I am having the same issue when I am using a row or column.
So here is my question, how do I implement it so that the grid goes to its relative attributed place and not at the top left corner and what's the reason for the same?
There is a post here that might answer my question but I'm not sure how to implement it in my case.