Как нарисовать изображение в определенной позиции в компоновке реактивного ранца
Я хочу нарисовать изображение в определенной позиции, где заканчивается белая дуга. Я рисую дугу с помощью этого ответа . Теперь я хочу нарисовать изображение над дугой. Я попробовал этот ответ , чтобы нарисовать изображение, но нет возможности рисовать изображение в определенном месте.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)
}
)
}
}
}