簡體   English   中英

如何在 Jetpack Compose 中使用 Canvas 繪制彩色條?

[英]How to draw a multicolored bar with Canvas in Jetpack Compose?

如何在 Compose 中獲得這樣的 UI?

堆疊條

假設有一個切片列表:

data class Slice(val value: Float, val color: Color)

Group-1 是 14.6,紅色

Group-2 是 61.8,藍色

Group-3 是 23.6,綠色

總計 100.0

Canvas 無論如何都不是必需的。

如果我們不使用 canvas,我們可以使用浮動百分比值作為RowColumn子級的weight

val slices = listOf(
    Slice(value = 14.6f, color = Color(0XFFe31a1a), text = "55"),
    Slice(value = 61.8f, color = Color(0XFF377eb8), text = "233"),
    Slice(value = 23.6f, color = Color(0XFF49a345), text = "89")
)

var state by remember { mutableStateOf(.0f) }
val width = animateFloatAsState(targetValue = state, animationSpec = tween(300))

LaunchedEffect(key1 = Unit, block = {
    delay(1000L)
    state = 1f
})

Row(
    modifier = Modifier
       .padding(14.dp)
       .height(64.dp)
       .fillMaxWidth(),
    ) {
       slices.forEach {
           Column(
               modifier = Modifier
                  .fillMaxHeight()
                  .weight(it.value),
               horizontalAlignment = Alignment.CenterHorizontally
           ) {
               Text(
                   text = it.value.toString(),
                   color = Color.Black,
                   modifier = Modifier.padding(4.dp)
               )
               Box(
                   modifier = Modifier
                       .fillMaxSize()
                       .background(it.color),
                   contentAlignment = Alignment.Center
               ) {
                  Text(text = it.text, color = Color.White)
                 }
             }
         }
     }

結果:

更新了您的切片數據 class 以包含文本以繪制文本。 如果您不想繪制文本,可以將其刪除

data class Slice(val value: Float, val color: Color, val text: String = "")

和 Canvas 繪制矩形和文字

@OptIn(ExperimentalTextApi::class)
@Composable
private fun StackedBar(modifier: Modifier, slices: List<Slice>) {

    val textMeasurer = rememberTextMeasurer()

    val textLayoutResults = remember {
        mutableListOf<TextLayoutResult>().apply {
            slices.forEach {
                val textLayoutResult: TextLayoutResult =
                    textMeasurer.measure(
                        text = AnnotatedString(it.text),
                        style = TextStyle(
                            color = Color.White,
                            fontSize = 18.sp
                        )
                    )
                add(textLayoutResult)
            }
        }
    }

    Canvas(modifier = modifier) {
        val canvasWidth = size.width
        val canvasHeight = size.height

        var currentX = 0f
        slices.forEachIndexed { index: Int, slice: Slice ->
            val width = (slice.value) / 100f * canvasWidth

            // Draw Rectangles
            drawRect(
                color = slice.color, topLeft = Offset(currentX, 0f), size = Size(
                    width,
                    canvasHeight
                )
            )

            // Draw Text
            val textSize = textLayoutResults[index].size
            val style = textLayoutResults[index].layoutInput.style
            drawText(
                textMeasurer = textMeasurer, text = slice.text, topLeft = Offset(
                    x = currentX + (width - textSize.height) / 2,
                    y = (canvasHeight - textSize.height) / 2
                ),
                style = style
            )

            // Update start position of next rectangle
            currentX += width
        }
    }
}

用法

Column {
    val slices = listOf(
        Slice(value = 14.6f, color = Color.Red, text = "55"),
        Slice(value = 61.8f, color = Color.Blue, text = "233"),
        Slice(value = 23.6f, color = Color.Green, text = "89")
    )

    StackedBar(
        modifier = Modifier
            .fillMaxWidth()
            .height(100.dp),
        slices = slices
    )
}

結果

在此處輸入圖像描述

景觀

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM