自定义上下两个方向的柱形图
用compose绘制一个自定义的柱形图标,上面表示一个列表值,下方表示另外一个列表值
@Composable
fun ProgramBarChartCompose(modifier: Modifier = Modifier,upValues: List<Float?>,downValues: List<Float?>,currentIndex: Int,) {val colorUp = Color(0xFF5284FF)val colorDown = Color(0xFF8CD359)val colorDefault = Color(0xFF31426D)val maxUpValue = maxOf(6f, upValues.filterNotNull().maxOrNull() ?: 0f) + 1val maxDownValue = maxOf(6f, downValues.filterNotNull().maxOrNull() ?: 0f) + 1val barCount = upValues.size.coerceAtLeast(1)Canvas(modifier = modifier) {val totalWeight = 120f + 50fval upRegionHeight = size.height * (120f / totalWeight)val downRegionHeight = size.height * (50f / totalWeight)val splitBaseLine = upRegionHeightval totalParts = barCount * 4 + (barCount + 1) * 5val unit = size.width / totalPartsval barWidth = unit * 4val barSpacing = unit * 5for (i in 0 until barCount) {val cx = i * (barWidth + barSpacing) + barSpacingval upVal = upValues.getOrNull(i)val downVal = downValues.getOrNull(i)val isActive = i <= currentIndexval upColor = if (isActive) colorUp else colorDefaultval downColor = if (isActive) colorDown else colorDefault// --- Up Bar ---if (upVal != null && maxUpValue > 0) {val upHeight = (upVal / maxUpValue).coerceIn(0f, 1f) * upRegionHeightval upTop = splitBaseLine - upHeightval rect = Rect(offset = Offset(cx, upTop),size = Size(barWidth, upHeight))val roundRect = RoundRect(rect = rect,topLeft = CornerRadius(barWidth / 2),topRight = CornerRadius(barWidth / 2),bottomLeft = CornerRadius(0f),bottomRight = CornerRadius(0f))val path = Path().apply {addRoundRect(roundRect, Direction.Clockwise)}drawPath(path = path, color = upColor)}// --- Down Bar ---if (downVal != null && maxDownValue > 0) {val downHeight = (downVal / maxDownValue).coerceIn(0f, 1f) * downRegionHeightval rect = Rect(offset = Offset(cx, splitBaseLine),size = Size(barWidth, downHeight))val roundRect = RoundRect(rect = rect,topLeft = CornerRadius(0f),topRight = CornerRadius(0f),bottomLeft = CornerRadius(barWidth / 2),bottomRight = CornerRadius(barWidth / 2))val path = Path().apply {addRoundRect(roundRect, Direction.Clockwise)}drawPath(path = path, color = downColor)}}}
}
如果想要给某个view画上边框或者下边框
/*** 自定义边框* @param strokeWidthDp 边框宽度* @param cornerRadiusDp 圆角* @param borderColor 颜色* @param noTop 不要上面的线,只画两边*/
fun Modifier.drawUpBorder(strokeWidthDp: Dp = 2.dp,cornerRadiusDp: Dp = 8.dp,borderColor: Color = Color_EE4343,noTop: Boolean = false
) =this.drawWithContent {drawContent()if (strokeWidthDp > 0.dp) {val strokeWidth = strokeWidthDp.toPx()val cornerRadius = cornerRadiusDp.toPx()// 创建绘制三边的路径val path = Path().apply {// 起始点:左上圆弧结束点 (右上角圆弧起始点)moveTo(0f, cornerRadius)// 绘制左边线 (从上到下)lineTo(0f, size.height)// 3. 左上圆角 (从下向上到左向右) - 顺时针90度arcTo(rect = Rect(0f, 0f, cornerRadius * 2, cornerRadius * 2),startAngleDegrees = 180f,sweepAngleDegrees = 90f,forceMoveTo = false)if (noTop) {moveTo(size.width - cornerRadius, 0f)} else {// 4. 上边线lineTo(size.width - cornerRadius, 0f)}// 5. 右上圆角arcTo(rect = Rect(size.width - 2 * cornerRadius,0f,size.width,cornerRadius * 2),startAngleDegrees = 270f,sweepAngleDegrees = 90f,forceMoveTo = false)// 6. 右边线lineTo(size.width, size.height)}// 绘制边框路径drawPath(path = path, color = borderColor, style = Stroke(width = strokeWidth,cap = StrokeCap.Round,join = StrokeJoin.Round))}}fun Modifier.drawDownBorder(strokeWidthDp: Dp = 2.dp,cornerRadiusDp: Dp = 8.dp,borderColor: Color = Color_EE4343,noBottom: Boolean = false
) =this.drawWithContent {drawContent()if (strokeWidthDp > 0.dp) {val strokeWidth = strokeWidthDp.toPx()val cornerRadius = cornerRadiusDp.toPx()// 创建绘制三边的路径val path = Path().apply {// 1. 左下角开始点moveTo(0f, size.height - cornerRadius)// 2. 左下圆角(逆时针,从上往下到左往右)arcTo(rect = Rect(0f, size.height - 2 * cornerRadius, 2 * cornerRadius, size.height),startAngleDegrees = 180f,sweepAngleDegrees = 90f,forceMoveTo = false)if (noBottom) {// 只画左右边,跳过底边moveTo(size.width, size.height - cornerRadius)} else {// 3. 底部直线lineTo(size.width - cornerRadius, size.height)}// 4. 右下圆角(顺时针,从下往上到右往左)arcTo(rect = Rect(size.width - 2 * cornerRadius,size.height - 2 * cornerRadius,size.width,size.height),startAngleDegrees = 90f,sweepAngleDegrees = 90f,forceMoveTo = false)// 5. 右边线往上lineTo(size.width, 0f)// 6. 左边线往上moveTo(0f, size.height)lineTo(0f, 0f)}drawPath(path = path,color = borderColor,style = Stroke(width = strokeWidth,cap = StrokeCap.Round,join = StrokeJoin.Round))}}