You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose Canvas绘制垂直线:百分比转像素值问题

解决Jetpack Compose Canvas中百分比转像素绘制垂直线的问题

问题说明

在Jetpack Compose的Canvas中绘制垂直线时,直接将0-100%的Float类型百分比值作为Offset的x坐标,会导致所有垂直线紧密聚集,无法按比例分布在Canvas宽度上。核心问题是未将百分比值转换为对应Canvas宽度的像素值。

日志信息

Pixel in size 996.0
2023-02-12 19:02:01.063 13417-13417 MainActivity            com.example.queueapplication         E  name Low --++-- startPoint 0.0 --++-- endPoint 16.666666 
2023-02-12 19:02:01.064 13417-13417 MainActivity            com.example.queueapplication         E  name Normal --++-- startPoint 16.666666 --++-- endPoint 33.333332 
2023-02-12 19:02:01.064 13417-13417 MainActivity            com.example.queueapplication         E  name Elevated --++-- startPoint 33.333332 --++-- endPoint 50.0 
2023-02-12 19:02:01.064 13417-13417 MainActivity            com.example.queueapplication         E  name High --++-- startPoint 50.0 --++-- endPoint 66.666664 
2023-02-12 19:02:01.064 13417-13417 MainActivity            com.example.queueapplication         E  name Very High --++-- startPoint 66.666664 --++-- endPoint 83.33333 
2023-02-12 19:02:01.064 13417-13417 MainActivity            com.example.queueapplication         E  name Extremely High --++-- startPoint 83.33333 --++-- endPoint 100.0 

原尝试代码

@Composable
fun DrawProgressBar() {
    val activity = LocalContext.current as AppCompatActivity
    val rangeComposition = RangeComposition()
    val itemLst = rangeComposition.bpExplained
    val boxSize = 30.dp
    Box(
        modifier = Modifier
            .background(Color.LightGray)
            .height(height = boxSize)
    ) {
        Canvas(
            modifier = Modifier
                .fillMaxWidth()
        ) {
            val canvasWidth = size.width
            drawLine(
                start = Offset(x = 0f, y = (boxSize / 2).toPx()),
                end = Offset(x = canvasWidth, y = (boxSize / 2).toPx()),
                color = Color.Black,
                strokeWidth = 8.dp.toPx(),
            )
            activity.logE("Pixel in size $canvasWidth")
            itemLst.forEach { rangeItem -
                val endPointInPixel = rangeItem.endPoint
                activity.logE("name ${rangeItem.name} --++-- startPoint ${rangeItem.startPoint} --++-- endPoint ${rangeItem.endPoint} ")
                drawLine(
                    start = Offset(x = endPointInPixel, y = 0F),
                    end = Offset(x = endPointInPixel, y = boxSize.toPx()),
                    color = Color.Black,
                    strokeWidth = 4.dp.toPx(),
                )
            }
        }
    }
}

解决方案

核心是将百分比值转换为Canvas宽度对应的像素值,计算公式为:像素值 = 百分比值 / 100 * Canvas宽度。同时修正原代码中forEach lambda的语法错误(-改为->)。

修改后的完整代码:

@Composable
fun DrawProgressBar() {
    val activity = LocalContext.current as AppCompatActivity
    val rangeComposition = RangeComposition()
    val itemLst = rangeComposition.bpExplained
    val boxSize = 30.dp
    Box(
        modifier = Modifier
            .background(Color.LightGray)
            .height(height = boxSize)
    ) {
        Canvas(
            modifier = Modifier
                .fillMaxWidth()
        ) {
            val canvasWidth = size.width
            drawLine(
                start = Offset(x = 0f, y = (boxSize / 2).toPx()),
                end = Offset(x = canvasWidth, y = (boxSize / 2).toPx()),
                color = Color.Black,
                strokeWidth = 8.dp.toPx(),
            )
            activity.logE("Pixel in size $canvasWidth")
            itemLst.forEach { rangeItem ->
                // 将百分比转换为对应Canvas宽度的像素值
                val endPointInPixel = rangeItem.endPoint / 100 * canvasWidth
                activity.logE("name ${rangeItem.name} --++-- startPoint ${rangeItem.startPoint} --++-- endPoint ${rangeItem.endPoint} --++-- pixel $endPointInPixel")
                drawLine(
                    start = Offset(x = endPointInPixel, y = 0F),
                    end = Offset(x = endPointInPixel, y = boxSize.toPx()),
                    color = Color.Black,
                    strokeWidth = 4.dp.toPx(),
                )
            }
        }
    }
}

效果验证

  • 修改前:所有垂直线紧密聚集在Canvas左侧区域
  • 修改后:垂直线按百分比比例均匀分布在整个Canvas宽度上

内容的提问来源于stack exchange,提问作者Compose Learner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 13:05:17