MpAndroidChart横向柱状图正负柱子圆角实现问题求助
解决MPAndroidChart横向柱状图正负柱子圆角问题
你的现有实现主要问题在于没有针对正负柱子分别处理圆角位置,且采用「先画矩形再用CLEAR模式擦出圆角」的方式不仅容易出现绘制异常(比如图层混合问题),还无法实现单根柱子的独立圆角效果。下面是修正后的完整实现方案:
核心思路
- 对每个柱子单独绘制,根据数值正负判断圆角方向:
- 正值柱子:仅右侧(靠近X轴正方向)设置圆角
- 负值柱子:仅左侧(靠近X轴负方向)设置圆角
- (可根据需求调整为两端都圆角)
- 使用
Path构建带圆角的矩形路径,替代原有的画矩形+擦除方案,避免图层混合问题 - 正确结合动画的
phaseX/phaseY参数,保证动画过程中圆角效果正常
修正后的自定义Renderer代码
package com.almaraiquest.Utils import android.graphics.* import com.github.mikephil.charting.animation.ChartAnimator import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider import com.github.mikephil.charting.interfaces.datasets.IBarDataSet import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer import com.github.mikephil.charting.utils.ViewPortHandler class MyCustomChartRender( chart: BarDataProvider, animator: ChartAnimator, viewPortHandler: ViewPortHandler ) : HorizontalBarChartRenderer(chart, animator, viewPortHandler) { private val cornerRadius = 30f // 自定义圆角大小 private val path = Path() private val rectF = RectF() override fun drawDataSet(c: Canvas?, dataSet: IBarDataSet?, index: Int) { if (c == null || dataSet == null) return val trans = mChart.getTransformer(dataSet.axisDependency) val phaseX = mAnimator.phaseX val phaseY = mAnimator.phaseY val buffer = mBarBuffers[index] buffer.setPhases(phaseX, phaseY) buffer.setDataSet(index) buffer.setInverted(mChart.isInverted(dataSet.axisDependency)) buffer.feed(dataSet) trans.pointValuesToPixel(buffer.buffer) var j = 0 while (j < buffer.size()) { if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 3])) break if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[j + 1])) { j += 4 continue } // 获取当前柱子的四个边界坐标 val left = buffer.buffer[j] val top = buffer.buffer[j + 1] + 10f // 上下边距,和你原来的设置一致 val right = buffer.buffer[j + 2] val bottom = buffer.buffer[j + 3] - 10f // 获取当前柱子的数值,判断正负 val entry = dataSet.getEntryForIndex(j / 4) val value = entry.y // 构建带圆角的路径 path.reset() rectF.set(left, top, right, bottom) when { value > 0 -> { // 正值柱子:右侧圆角 path.addRoundRect( rectF, floatArrayOf(0f, 0f, cornerRadius, cornerRadius, cornerRadius, cornerRadius, 0f, 0f), Path.Direction.CW ) } value < 0 -> { // 负值柱子:左侧圆角 path.addRoundRect( rectF, floatArrayOf(cornerRadius, cornerRadius, 0f, 0f, 0f, 0f, cornerRadius, cornerRadius), Path.Direction.CW ) } else -> { // 零值柱子:无圆角或全圆角,按需调整 path.addRect(rectF, Path.Direction.CW) } } // 设置柱子颜色并绘制路径 mRenderPaint.color = dataSet.getColor(j / 4) c.drawPath(path, mRenderPaint) j += 4 } } }
关键细节说明
- 圆角方向控制:通过
floatArrayOf指定四个角的圆角半径,顺序为「左上、右上、右下、左下」,针对正负值分别设置对应角的半径 - 边界处理:保留了你原来的上下边距(
+10f/-10f),如果不需要可以移除 - 动画兼容:依然使用原buffer的
phaseX/phaseY参数,保证柱状图动画过程中圆角效果同步 - 避免Xfermode问题:直接用Path绘制带圆角的形状,不需要依赖图层混合,绘制更稳定
配合你的配置代码使用
你的setHorizontalChart方法不需要修改,只需要确保设置自定义Renderer的代码正确即可:
val myCustomChartRender = MyCustomChartRender(horizonatal_chart, horizonatal_chart.animator, horizonatal_chart.viewPortHandler) horizonatal_chart.renderer = myCustomChartRender
如果需要调整圆角大小,直接修改cornerRadius变量的值即可。
内容的提问来源于stack exchange,提问作者sak
相关产品推荐
相关产品推荐

