自定义布局不会改变其相对于其他元素的位置
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)
}
}
}
我创建了一个自定义布局来创建六边形网格,但是,当我将网格与其他元素放置在一起时,例如在行或列中,网格不会更新其位置并保持在左上角地图一角。
这是我的代码:
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)
}
}
}