MPAndroidChart堆叠柱状图实现整体圆角效果的问题咨询
MPAndroidChart 堆叠柱状图整体圆角实现方案
问题的核心原因是原有逻辑会为每个柱形分段单独绘制圆角,只需调整绘制逻辑,将同一横坐标下的所有堆叠段归为一组,统一判断每个分段的位置后再决定圆角位置即可。
实现逻辑说明
- 先对buffer中的数据按横坐标分组,相同左右x坐标的属于同一根柱子的堆叠分段
- 计算每组柱子的整体顶部和底部边界
- 遍历组内每个分段:
- 仅顶部段添加上圆角
- 仅底部段添加下圆角
- 中间段直接绘制直角矩形
调整后的代码
val trans: Transformer = mChart.getTransformer(dataSet.axisDependency) mShadowPaint.color = dataSet.barShadowColor val phaseX = mAnimator.phaseX val phaseY = mAnimator.phaseY // 初始化buffer val buffer = mBarBuffers[index] buffer.setPhases(phaseX, phaseY) buffer.setDataSet(index) buffer.setBarWidth(mChart.barData.barWidth) buffer.setInverted(mChart.isInverted(dataSet.axisDependency)) buffer.feed(dataSet) trans.pointValuesToPixel(buffer.buffer) // 先对buffer数据按柱子分组,相同x左右坐标的为同一根柱子 val barGroups = mutableListOf<MutableList<FloatArray>>() var currentXLeft = -1f var j = 0 while (j < buffer.size()) { val xLeft = buffer.buffer[j] val yTop = buffer.buffer[j + 1] val xRight = buffer.buffer[j + 2] val yBottom = buffer.buffer[j + 3] if (xLeft != currentXLeft) { barGroups.add(mutableListOf()) currentXLeft = xLeft } barGroups.last().add(floatArrayOf(xLeft, yTop, xRight, yBottom)) j += 4 } if (dataSet.colors.size > 1) { var colorIndex = 0 barGroups.forEachIndexed { groupIdx, segments -> val firstSeg = segments.first() val xLeft = firstSeg[0] val xRight = firstSeg[2] if (!mViewPortHandler.isInBoundsLeft(xRight)) return@forEachIndexed if (!mViewPortHandler.isInBoundsRight(xLeft)) return@forEachIndexed // 绘制阴影 if (mChart.isDrawBarShadowEnabled) { if (mRadius > 0) c.drawRoundRect( RectF( xLeft, mViewPortHandler.contentTop(), xRight, mViewPortHandler.contentBottom() ), mRadius, mRadius, mShadowPaint ) else c.drawRect( xLeft, mViewPortHandler.contentTop(), xRight, mViewPortHandler.contentBottom(), mShadowPaint ) } // 计算整根柱子的上下边界 val allTops = segments.map { it[1] } val allBottoms = segments.map { it[3] } val barTop = allTops.minOrNull() ?: 0f val barBottom = allBottoms.maxOrNull() ?: 0f segments.forEach { seg -> val segTop = seg[1] val segBottom = seg[3] mRenderPaint.color = dataSet.getColor(colorIndex % dataSet.colors.size) colorIndex++ if (mRadius <= 0) { c.drawRect(xLeft, segTop, xRight, segBottom, mRenderPaint) return@forEach } // 判断当前段的位置,设置对应圆角 val corners = FloatArray(8) { 0f } // 是顶部段,加上圆角 if (segTop == barTop) { corners[0] = mRadius corners[1] = mRadius corners[2] = mRadius corners[3] = mRadius } // 是底部段,加下圆角 if (segBottom == barBottom) { corners[4] = mRadius corners[5] = mRadius corners[6] = mRadius corners[7] = mRadius } val path = Path() path.addRoundRect(RectF(xLeft, segTop, xRight, segBottom), corners, Path.Direction.CW) c.drawPath(path, mRenderPaint) } } } else { mRenderPaint.color = dataSet.color barGroups.forEach { segments -> val firstSeg = segments.first() val xLeft = firstSeg[0] val xRight = firstSeg[2] if (!mViewPortHandler.isInBoundsLeft(xRight)) return@forEach if (!mViewPortHandler.isInBoundsRight(xLeft)) return@forEach // 绘制阴影 if (mChart.isDrawBarShadowEnabled) { if (mRadius > 0) c.drawRoundRect( RectF( xLeft, mViewPortHandler.contentTop(), xRight, mViewPortHandler.contentBottom() ), mRadius, mRadius, mShadowPaint ) else c.drawRect( xLeft, firstSeg[1], xRight, firstSeg[3], mShadowPaint ) } // 计算整根柱子的上下边界 val allTops = segments.map { it[1] } val allBottoms = segments.map { it[3] } val barTop = allTops.minOrNull() ?: 0f val barBottom = allBottoms.maxOrNull() ?: 0f segments.forEach { seg -> val segTop = seg[1] val segBottom = seg[3] if (mRadius <= 0) { c.drawRect(xLeft, segTop, xRight, segBottom, mRenderPaint) return@forEach } // 判断当前段的位置,设置对应圆角 val corners = FloatArray(8) { 0f } // 是顶部段,加上圆角 if (segTop == barTop) { corners[0] = mRadius corners[1] = mRadius corners[2] = mRadius corners[3] = mRadius } // 是底部段,加下圆角 if (segBottom == barBottom) { corners[4] = mRadius corners[5] = mRadius corners[6] = mRadius corners[7] = mRadius } val path = Path() path.addRoundRect(RectF(xLeft, segTop, xRight, segBottom), corners, Path.Direction.CW) c.drawPath(path, mRenderPaint) } } }
兼容说明
该逻辑同时兼容堆叠和非堆叠模式:非堆叠模式下每个分组只有一个分段,会同时添加上下圆角,和原有效果保持一致。
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

