如何在Jetpack Compose中实现堆叠彩色条形UI(Canvas可选)
在Jetpack Compose中实现堆叠条形UI的两种方法
方法一:使用基础布局组件(无需Canvas)
这种方法简洁直观,借助Compose的基础布局组件就能快速实现堆叠条形效果,适合大多数常规场景。
实现逻辑
利用Row作为容器,通过weight修饰符按数值比例分配每个分段的宽度,再给每个分段设置对应背景色即可。因为你的数据总和正好是100,直接用slice.value作为权重比例即可。
完整代码
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp data class Slice(val value: Float, val color: Color) @Composable fun StackedBarWithLayout() { val slices = listOf( Slice(14.6f, Color.Red), Slice(61.8f, Color.Blue), Slice(23.6f, Color.Green) ) Row(modifier = Modifier.height(40.dp)) { slices.forEach { slice -> Box( modifier = Modifier .weight(slice.value / 100f) .background(slice.color) ) } } }
方法二:使用Canvas绘制
如果需要更灵活的自定义效果(比如添加圆角、动态动画、分段标记等),可以用Canvas手动绘制每个条形分段。
实现逻辑
在Canvas中获取画布宽度,遍历分段数据计算每个分段的起始X坐标和宽度,依次绘制矩形即可。
完整代码
import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.Fill import androidx.compose.ui.unit.dp @Composable fun StackedBarWithCanvas() { val total = 100.0f val slices = listOf( Slice(14.6f, Color.Red), Slice(61.8f, Color.Blue), Slice(23.6f, Color.Green) ) Canvas(modifier = Modifier.fillMaxWidth().height(40.dp)) { val canvasWidth = size.width var currentX = 0f slices.forEach { slice -> val segmentWidth = (slice.value / total) * canvasWidth drawRect( color = slice.color, topLeft = androidx.compose.ui.geometry.Offset(currentX, 0f), size = androidx.compose.ui.geometry.Size(segmentWidth, size.height), style = Fill ) currentX += segmentWidth } } }
可选扩展优化
- 给分段添加圆角:在
drawRect中传入cornerRadius参数 - 添加点击交互:在布局方法中给
Box添加clickable修饰符 - 实现加载动画:用
animateFloatAsState过渡分段的宽度值
内容的提问来源于stack exchange,提问作者imn
相关产品推荐
相关产品推荐

