kotlin 在Jetpack合成中使用偏移动画在单元格下移动的片段

np8igboo  于 2023-06-24  发布在  Kotlin
关注(0)|答案(1)|浏览(138)

我正在Kotlin中使用Jetpack Compose实现一个国际象棋游戏。棋盘有8x8的格子,我有白色和黑子。当白色棋子从底部向顶部移动时,一切似乎都正常工作。然而,当黑色棋子从顶部移动到底部时,它们会在第一行的单元格下面移动,当它们继续移动时,它们会在第二行的单元格下面移动,依此类推。
以下是渲染棋盘和棋子的相关代码:

@Composable
fun RenderChessBoard(
    chessBoardState: ChessBoard,
    composableScope: CoroutineScope = rememberCoroutineScope(),
    onPieceMove: (ChessPiece, Position) -> Unit
) {
    var cellSize by remember { mutableStateOf(IntSize(0, 0)) }
    val selectedPiece = remember { mutableStateOf<ChessPiece?>(null) }
    var pieceOffsets by remember { mutableStateOf<Map<ChessPiece, IntOffset>>(emptyMap()) }

    Column {
        chessBoardState.cells.forEachIndexed { rowIndex, row ->
            Row {
                row.forEachIndexed { columnIndex, piece ->
                    val currentPosition = Position(rowIndex, columnIndex)
                    val cellColor =
                        determineCellColor(selectedPiece.value, currentPosition, chessBoardState)

                    Box(
                        modifier = Modifier
                            .weight(1f)
                            .onSizeChanged { if (cellSize.width == 0) cellSize = it }
                            .aspectRatio(1f)
                            .background(cellColor),
                        contentAlignment = Alignment.Center
                    ) {
                        DrawAvailableMoves(
                            selectedPiece = selectedPiece.value,
                            currentPosition = currentPosition,
                            chessBoard = chessBoardState,
                            onPieceMove = { chessPiece, targetPosition ->
                                pieceOffsets = pieceOffsets + (chessPiece to IntOffset(
                                    ((targetPosition.column - chessPiece.position.column) * cellSize.width),
                                    ((targetPosition.row - chessPiece.position.row) * cellSize.height)
                                ))
                                composableScope.launch {
                                    delay(ANIMATION_DURATION_MS)
                                    onPieceMove.invoke(chessPiece, targetPosition)
                                }
                                selectedPiece.value = null
                            }
                        )

                        piece?.let { currentPiece ->
                            val targetPosition = pieceOffsets[currentPiece] ?: IntOffset(0, 0)
                            val offsetState by animateIntOffsetAsState(
                                targetValue = targetPosition,
                                animationSpec = tween(durationMillis = ANIMATION_DURATION_MS.toInt()),
                            )

                            PieceView(
                                modifier = Modifier
                                    .offset { offsetState }
                                    .fillMaxSize(),
                                piece = currentPiece,
                                
                                    ...
                        }
                    }
                }
            }
        }
    }
}

我已经注意到这个问题似乎是与渲染的作品,但我不能查明确切的问题。here's screen from layout inspector
我怎样才能防止碎片在向上移动时(有时是向右移动)从单元格下面穿过?我错过了什么?任何指导或建议都很感激!

stszievb

stszievb1#

当父级的子组合被布局时,最后一个组合被绘制在顶部,你可以清楚地看到,Box堆叠或使用Placeable.placeRelative(0,0)。对于行或列,您可以使用偏移来观察这种行为,就像在您的情况中一样。
例如,当您将2个组合物放置为

@Preview
@Composable
private fun Test() {
    Column(
        modifier = Modifier
            .padding(30.dp)
            .fillMaxSize()
    ) {
        Box(
            modifier = Modifier
                .size(100.dp)
                .background(Color.Yellow)
        )

        Box(
            modifier = Modifier
                .offset(0.dp, (-50).dp)
                .size(100.dp)
                .background(Color.Red)
        )
    }
}

但是,您可以使用Modifier.zIndex来更改子组合物的绘制顺序。
创建一个修改器,用于控制同一布局父项的子项的绘图顺序。具有较大zIndex的子对象将被绘制在具有较小zIndex的所有子对象的顶部。当子级具有相同的zIndex时,使用父级放置子级的原始顺序。请注意,如果有多个zIndex修改器应用于同一布局,则其值的总和将用作最终的zIndex。如果布局没有应用zIndex,则默认zIndex为0。

@Preview
@Composable
private fun Test2() {
    Column(
        modifier = Modifier
            .padding(30.dp)
            .fillMaxSize()
    ) {
        Box(
            modifier = Modifier
                .zIndex(1f)
                .size(100.dp)
                .background(Color.Yellow)
        )

        Box(
            modifier = Modifier
                .offset(0.dp, (-50).dp)
                .size(100.dp)
                .background(Color.Red)
        )
    }
}

相关问题