Путь рисования на холсте для создания реактивного ранца не работает

#kotlin #android-jetpack-compose

Вопрос:

У меня есть эта композиция, которая должна позволять рисовать указателем на холст, но когда я перемещаю указатель, ничего не происходит

 @ExperimentalComposeUiApi
@Composable
fun CanvasDraw() {
    val path = remember { Path() }

    Canvas(modifier = Modifier
        .fillMaxSize()
        .pointerInteropFilter {
            when (it.action) {
                MotionEvent.ACTION_DOWN -> {
                    path.moveTo(it.x, it.y)
                }
                MotionEvent.ACTION_MOVE -> {
                    path.lineTo(it.x, it.y)
                }
                else -> false
            }
            true
        }) {
        drawPath(
            path = path,
            color = Color.Blue,
            style = Stroke(10f)
        )
    }
}
 

Ответ №1:

remember { Path() } кэширует значение лямбда-содержимого для следующих перекомпозиций, но оно не может вызвать перекомпозицию при изменении содержимого этого объекта. Чтобы создать какое — то состояние, которое вызовет перекомпозицию при изменениях в Compose, вам нужно использовать какое-то изменяемое состояние-это новая вещь, созданная для Compose.

Вы можете найти более подробную информацию о состоянии в Compose в документации, включая это видео на YouTube, в котором объясняются основные принципы.

Хранение точек внутри Path не будет чистым, так как это не базовый тип. Вместо этого я использую список изменяемых состояний точек, например:

 val points = remember { mutableStateListOf<Offset>() }

Canvas(modifier = Modifier
    .fillMaxSize()
    .pointerInput(Unit) {
        detectDragGestures { change, _ ->
            points.add(change.position)
        }
    }
) {
    drawPath(
        path = Path().apply {
            points.forEachIndexed { i, point ->
                if (i == 0) {
                    moveTo(point.x, point.y)
                } else {
                    lineTo(point.x, point.y)
                }
            }
        },
        color = Color.Blue,
        style = Stroke(10f)
    )
}