我的自定义布局中有一个可拖动的修饰符。问题是我所有的可放置物都作为一个块移动,而我希望它们单独移动。循环遍历它们以确保一次只选择一个放置的正确方法是什么?或者有没有更好的方法来解决它?这是我的自定义布局:
@Composable
fun CustomLayout(
modifier: Modifier = Modifier,
content: @Composable() () -> Unit
) {
val coroutineScope = rememberCoroutineScope()
val offsetX = remember { Animatable(0f) }
val offsetY = remember { Animatable(0f) }
Layout(
modifier = modifier
.offset {
IntOffset(
offsetX.value.roundToInt(),
offsetY.value.roundToInt()
)
}
.draggable(
state = rememberDraggableState { delta ->
coroutineScope.launch {
offsetX.snapTo(offsetX.value + delta)
}
},
orientation = Orientation.Horizontal,
onDragStarted = {},
onDragStopped = {
coroutineScope.launch {
offsetX.animateTo(
targetValue = 0f,
animationSpec = tween(
durationMillis = 1000,
delayMillis = 0
)
)
}
}
),
content = content
) { measurables, constraints ->
val tileSize = constraints.maxWidth / 7
val childConstraints = constraints.copy(
minWidth = minOf(constraints.minWidth, tileSize),
maxWidth = tileSize
)
val placeables = measurables.map { measurable ->
measurable.measure(childConstraints)
}
layout(constraints.maxWidth, constraints.maxHeight) {
var yPosition = 0
val xPosition = 0
placeables.forEachIndexed { index, placeable ->
if (index <= 6) {
placeable.placeRelative(x = xPosition, y = yPosition)
} else {
placeable.placeRelative(
constraints.maxWidth - tileSize,
yPosition - placeable.height * 7
)
}
yPosition += placeable.height
}
}
}
}
这里我想一次只移动一个图块:
答案 0 :(得分:2)
您的解决方案不起作用,因为您将偏移应用于整个布局,但您需要将其应用于单个项目。
Layout
仅用于布局项目:在 MeasureScope
中,我们只能访问项目大小/位置,我们不能向它们添加修饰符,因为它们会修改状态和它'会导致递归。
我的建议是将项目计数和项目生成器传递给您的 Composable,以便我们可以为每个项目添加偏移和可拖动修饰符:
@Composable
fun DraggableLayout(
modifier: Modifier = Modifier,
count: Int,
item: @Composable (Int, Modifier) -> Unit
) {
val coroutineScope = rememberCoroutineScope()
val offsetsX = remember { mutableStateMapOf<Int, Animatable<Float, AnimationVector1D>>() }
CustomLayout(
modifier = modifier,
content = {
for (i in 0 until count) {
item(
i,
Modifier
.offset {
IntOffset(
offsetsX[i]?.value?.roundToInt() ?: 0,
0
)
}
.draggable(
state = rememberDraggableState { delta ->
coroutineScope.launch {
val offsetX = offsetsX[i] ?: Animatable(0f)
offsetX.snapTo(offsetX.value + delta)
offsetsX[i] = offsetX
}
},
orientation = Orientation.Horizontal,
onDragStarted = {},
onDragStopped = {
coroutineScope.launch {
offsetsX[i]!!.animateTo(
targetValue = 0f,
animationSpec = tween(
durationMillis = 1000,
delayMillis = 0
)
)
}
}
),
)
}
}
)
}
@Composable
fun CustomLayout(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Layout(
modifier = modifier,
content = content,
) { measurables, constraints ->
val tileSize = constraints.maxWidth / 7
val childConstraints = constraints.copy(
minWidth = minOf(constraints.minWidth, tileSize),
maxWidth = tileSize
)
val placeables = measurables.map { measurable ->
measurable.measure(childConstraints)
}
layout(constraints.maxWidth, constraints.maxHeight) {
var yPosition = 0
val xPosition = 0
placeables.forEachIndexed { index, placeable ->
if (index <= 6) {
placeable.placeRelative(x = xPosition, y = yPosition)
} else {
placeable.placeRelative(
constraints.maxWidth - tileSize,
yPosition - placeable.height * 7
)
}
yPosition += placeable.height
}
}
}
}
像这样使用它:
CustomLayout(
count = 10,
item = { i, modifier ->
Text(
"Test $i",
modifier = Modifier
.size(50.dp)
.then(modifier)
)
}
)