Как нарисовать изображение в определенной позиции в компоновке реактивного ранца

Я хочу нарисовать изображение в определенной позиции, где заканчивается белая дуга. Я рисую дугу с помощью этого ответа . Теперь я хочу нарисовать изображение над дугой. Я попробовал этот ответ , чтобы нарисовать изображение, но нет возможности рисовать изображение в определенном месте.Xпозиция. Итак, я что-то пробовал, но ничего не работает, не могли бы вы указать мне, где я ошибаюсь?

      @Composable
fun DrawProgressBar() {
    val activity = LocalContext.current as AppCompatActivity
    val rangeComposition = RangeComposition()
    val itemLst = rangeComposition.bpExplained
    val boxSize = 30.dp
    val brush = Brush.horizontalGradient(listOf(Color.Red, Color.Blue))
    val progressBarPointer = rangeComposition.findReadingWithPointer(142, 90).second
    val vector = ImageVector.vectorResource(id = R.drawable.ic_rectangle)
    val painter = rememberVectorPainter(image = vector)
    Box(
        modifier = Modifier
            .background(Color.White)
            .height(height = boxSize)
    ) {
        Canvas(
            modifier = Modifier
                .fillMaxSize()
                .graphicsLayer(alpha = 0.99f)
        ) {
            val strokeWidth = 8.dp
            val canvasWidth = size.width
            val canvasHeight = size.height
            val strokeWidthPx = density.run { strokeWidth.toPx() }
            val pathEffect = PathEffect.dashPathEffect(floatArrayOf(canvasHeight / 19, canvasHeight / 19), 0f)
            with(painter) {
                draw(painter.intrinsicSize)
            }
            drawLine(
                start = Offset(x = 0f, y = canvasHeight / 2),
                end = Offset(x = canvasWidth, y = canvasHeight / 2),
                color = Color.Gray,
                strokeWidth = strokeWidthPx,
                cap = StrokeCap.Round,
            )
            val progressBarPointerInPixel = (progressBarPointer / 100f) * canvasWidth
            drawLine(
                color = Color.White,
                start = Offset(x = progressBarPointerInPixel, y = canvasHeight / 2),
                end = Offset(x = progressBarPointerInPixel + strokeWidthPx / 2, y = canvasHeight / 2),
                strokeWidth = strokeWidthPx,
                blendMode = BlendMode.DstOut,
            )
            drawLine(
                brush = brush,
                start = Offset(x = 0f, y = canvasHeight / 2),
                end = Offset(x = progressBarPointerInPixel, y = canvasHeight / 2),
                strokeWidth = strokeWidthPx,
                cap = StrokeCap.Round,
            )
            drawArc(
                topLeft = Offset(x = progressBarPointerInPixel, y = canvasHeight / 2 - strokeWidthPx / 2),
                size = Size(strokeWidthPx, strokeWidthPx),
                color = Color.White,
                startAngle = -90f,
                sweepAngle = 180f,
                useCenter = true,
                blendMode = BlendMode.DstOut,
            )
            itemLst.forEachIndexed { index, rangeItem ->
                val endPointInPixel = (rangeItem.endPoint / 100f) * canvasWidth
                if (index != itemLst.lastIndex) {
                    drawLine(
                        start = Offset(x = endPointInPixel, y = 0F),
                        end = Offset(x = endPointInPixel, y = boxSize.toPx()),
                        color = Color.Black,
                        strokeWidth = 1.2.dp.toPx(),
                        pathEffect = pathEffect
                    )
                }
            }
        }
    }
}

Фактический результат

Ожидаемый результат

ОБНОВЛЯТЬ

После предложений @GabrieleMariotti я попытался выглядеть так

Код

      @Composable
fun DrawProgressBar() {
    val activity = LocalContext.current as AppCompatActivity
    val rangeComposition = RangeComposition()
    val itemLst = rangeComposition.bpExplained
    val boxSize = 30.dp
    val brush = Brush.horizontalGradient(listOf(Color.Red, Color.Blue))
    val progressBarPointer = rangeComposition.findReadingWithPointer(142, 90).second
    Box(
        modifier = Modifier
            .background(Color.White)
            .height(height = 36.dp)
    ) {
        Canvas(
            modifier = Modifier
                .fillMaxSize()
        ) {

            val rectSize = Size (30f,30f)

            val rect = Rect(Offset.Zero, rectSize)
            val trianglePath = Path().apply {
                moveTo(rect.bottomCenter.x, rect.bottomCenter.y)
                lineTo(rect.topRight.x , rect.topRight.y)
                lineTo(rect.topLeft.x, rect.topLeft.y)
                close()
            }

            drawIntoCanvas { canvas ->

                translate (30f,30f){
                    canvas.drawOutline(
                        outline = Outline.Generic(trianglePath),
                        paint = Paint().apply {
                            color = Color.Black
                            pathEffect = PathEffect.cornerPathEffect(rect.maxDimension / 3)
                        }
                    )
                }
            }

            val strokeWidth = 8.dp
            val canvasWidth = size.width
            val canvasHeight = size.height
            val strokeWidthPx = density.run { strokeWidth.toPx() }
            val pathEffect = PathEffect.dashPathEffect(floatArrayOf(canvasHeight / 19, canvasHeight / 19), 0f)
            drawLine(
                start = Offset(x = 0f, y = canvasHeight / 2),
                end = Offset(x = canvasWidth, y = canvasHeight / 2),
                color = Color.Gray,
                strokeWidth = strokeWidthPx,
                cap = StrokeCap.Round,
            )
            val progressBarPointerInPixel = (progressBarPointer / 100f) * canvasWidth
            drawLine(
                color = Color.White,
                start = Offset(x = progressBarPointerInPixel, y = canvasHeight / 2),
                end = Offset(x = progressBarPointerInPixel + strokeWidthPx / 2, y = canvasHeight / 2),
                strokeWidth = strokeWidthPx,
            )
            drawLine(
                brush = brush,
                start = Offset(x = 0f, y = canvasHeight / 2),
                end = Offset(x = progressBarPointerInPixel, y = canvasHeight / 2),
                strokeWidth = strokeWidthPx,
                cap = StrokeCap.Round,
            )
            drawArc(
                topLeft = Offset(x = progressBarPointerInPixel, y = canvasHeight / 2 - strokeWidthPx / 2),
                size = Size(strokeWidthPx, strokeWidthPx),
                color = Color.White,
                startAngle = -90f,
                sweepAngle = 180f,
                useCenter = true
            )
            itemLst.forEachIndexed { index, rangeItem ->
                val endPointInPixel = (rangeItem.endPoint / 100f) * canvasWidth
                if (index != itemLst.lastIndex) {
                    drawLine(
                        start = Offset(x = endPointInPixel, y = 0F),
                        end = Offset(x = endPointInPixel, y = boxSize.toPx()),
                        color = Color.Black,
                        strokeWidth = 1.2.dp.toPx(),
                        pathEffect = pathEffect
                    )
                }
            }
        }
    }
}

1 ответ

вCanvasчтобы нарисовать изображение в определенной позиции, вы можете применить translateфункция.

Перевести координатное пространство на заданную дельту в пикселях в координатах x и y соответственно.

Что-то вроде:

      Canvas(modifier = Modifier.fillMaxSize()){

    translate(
        left = 10f,
        top = 10f
    ) {
        with(painter) {
            draw(
                size = painter.intrinsicSize,
            )
        }
    }
}

Обратите внимание, что вы можете нарисовать треугольник вместо изображения.

          Canvas(modifier = Modifier.fillMaxSize()){

        //triangle size
        val rectSize = Size (60f,60f)
        
        val rect = Rect(Offset.Zero, rectSize)
        val trianglePath = Path().apply {
            moveTo(rect.bottomCenter.x, rect.bottomCenter.y)
            lineTo(rect.topRight.x , rect.topRight.y)
            lineTo(rect.topLeft.x, rect.topLeft.y)
            close()
        }

        drawIntoCanvas { canvas ->
            
            translate (30f,30f){
                canvas.drawOutline(
                    outline = Outline.Generic(trianglePath),
                    paint = Paint().apply {
                        color = Teal200
                        pathEffect = PathEffect.cornerPathEffect(rect.maxDimension / 3)
                    }
                )
            }
        }
    }

Другие вопросы по тегам