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
相关产品推荐
相关产品推荐

