自定义布局不会改变其相对于其他元素的位置

Custom Layout won't change its position relative to other elements

我创建了一个自定义布局来创建六边形网格,但是,当我将网格与其他元素放置在一起时,例如在行或列中,网格不会更新其位置并保持在左上角地图一角。

这是我的代码:

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)")
            }
        }
    }
}

如您所见,我正在使用 ConstraintLayout。网格的相对位置不会改变,我不知道为什么,我在使用行或列时遇到同样的问题。

所以这是我的问题,我该如何实现它才能使网格到达其相对属性位置而不是左上角,原因是什么?

有一个 post 可能会回答我的问题,但我不确定如何在我的案例中实施它。

除了在网格上指定开始和结束约束外,还使用 ​​width = Dimension.fillToConstraints

此外,在您的代码中,leftContraint(从父级开始的约束)用于结束,rightConstraint(从父级开始的约束)用于开始。刚刚交换了这两个。

Column(
    modifier = Modifier
        .constrainAs(gridRef) {
            // corrected start and end constraints
            linkTo(start = leftConstraint, end = rightConstraint)
            width = Dimension.fillToConstraints
        }
) {

    Grid(
        modifier = Modifier,
        lineLength = 8
    ) {
        for (i in 1..64) {
            StandardTile(Color.Blue)
        }
    }

}