一开始。我的条形图是这样的
但是产品 给的原型图是这样的
条形图有的顶端有一个圆角
当时。所有的需求都做完了
只剩下这个圆角了
然后网上一顿搜,github csdn 简书 其他的一些博客 发现特别好的方法没有 我一脸懵逼。难道真要改源码吗? 然后继续一顿搜。 最后绝望了。 改源码吧
网上各种找。最后定位到绘制条形图的是BarChartRenderer类下的drawDataSet方法,那么就需要重写这个方法 那么就定义一个自己的类。用来重写源码
新建SuddleBarChartRenderer类 在里面这样写
import android.graphics.Canvas
import android.graphics.Path
import android.graphics.RectF
import com.github.mikephil.charting.animation.ChartAnimator
import com.github.mikephil.charting.highlight.Highlight
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet
import com.github.mikephil.charting.renderer.BarChartRenderer
import com.github.mikephil.charting.utils.Utils
import com.github.mikephil.charting.utils.ViewPortHandler
class SuddleBarChartRenderer(
chart: BarDataProvider?,
animator: ChartAnimator?,
viewPortHandler: ViewPortHandler?
) :
BarChartRenderer(chart, animator, viewPortHandler) {
val mBarShadowRectBuffer = RectF()
override fun drawDataSet(c: Canvas, dataSet: IBarDataSet, index: Int) {
val trans = mChart.getTransformer(dataSet.axisDependency)
mBarBorderPaint.color = dataSet.barBorderColor
mBarBorderPaint.strokeWidth = Utils.convertDpToPixel(dataSet.barBorderWidth)
val drawBorder = dataSet.barBorderWidth > 0f
val phaseX = mAnimator.phaseX
val phaseY = mAnimator.phaseY
// draw the bar shadow before the values
// draw the bar shadow before the values
if (mChart.isDrawBarShadowEnabled) {
mShadowPaint.color = dataSet.barShadowColor
val barData = mChart.barData
val barWidth = barData.barWidth
val barWidthHalf = barWidth / 2.0f
var x: Float
var i = 0
val count = Math.min(
Math.ceil((dataSet.entryCount.toFloat() * phaseX).toDouble()).toInt(),
dataSet.entryCount
)
while (i < count) {
val e = dataSet.getEntryForIndex(i)
x = e.x
mBarShadowRectBuffer.left = x - barWidthHalf
mBarShadowRectBuffer.right = x + barWidthHalf
trans.rectValueToPixel(mBarShadowRectBuffer)
if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right)) {
i++
continue
}
if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left)) break
mBarShadowRectBuffer.top = mViewPortHandler.contentTop()
mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom()
c.drawRect(mBarShadowRectBuffer, mShadowPaint)
i++
}
}
// initialize the buffer
// initialize the buffer
val buffer = mBarBuffers[index]
buffer.setPhases(phaseX, phaseY)
buffer.setDataSet(index)
buffer.setInverted(mChart.isInverted(dataSet.axisDependency))
buffer.setBarWidth(mChart.barData.barWidth)
buffer.feed(dataSet)
trans.pointValuesToPixel(buffer.buffer)
val isSingleColor = dataSet.colors.size == 1
if (isSingleColor) {
mRenderPaint.color = dataSet.color
}
var j = 0
while (j < buffer.size()) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) {
j += 4
continue
}
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) break
if (!isSingleColor) {
// Set the color for the currently drawn value. If the index
// is out of bounds, reuse colors.
mRenderPaint.color = dataSet.getColor(j / 4)
}
// c.drawRect(//以前的源码
// buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
// buffer.buffer[j + 3], mRenderPaint
// )
val rectF = RectF(
buffer.buffer[j],
buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3]
)
val path = Path()
path.addRoundRect(
rectF,
floatArrayOf(14f, 14f, 14f, 14f, 14f, 0f, 0f, 0f),
Path.Direction.CCW
)
c.drawPath(path, mRenderPaint)
if (drawBorder) {
c.drawPath(path, mRenderPaint)
}
j += 4
}
}
}
源码里是这样写的
c.drawRect(//以前的源码
buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint
)
使用了canvas的drawRect方法 绘制了矩形,所以要把绘制方法改成绘制有圆角的矩形
所以我改成了这样
val rectF = RectF(buffer.buffer[j],buffer.buffer[j + 1],buffer.buffer[j + 2], buffer.buffer[j + 3])
val path = Path()
path.addRoundRect(rectF,floatArrayOf(14f, 14f, 14f, 14f, 14f, 0f, 0f, 0f),Path.Direction.CCW)
那么。我调用了path方法 这个方法是用来绘制几何图形的
然后绘制了圆角矩形
哈哈
然后呢。要定义一个类CustomBarChart 用来传值
import android.content.Context
import android.util.AttributeSet
import com.github.mikephil.charting.charts.BarChart
class CustomBarChart : BarChart {
constructor(context: Context?) : super(context) {}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {}
constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context,
attrs,
defStyle) {
}
override fun init() {
super.init()
mRenderer = SuddleBarChartRenderer(this, mAnimator, mViewPortHandler)
}
}
传值以后,要把改写后的源码绑定到你的xml结构里,代码如下
<com.example.你的路径.CustomBarChart
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="180dp"
android:background="@color/white"
android:padding="3dp" />
然后呢,加载试一下如何, 结果发现,有bug 点击到条形图上以后,有两种框,一种是修改的圆角,另一种是点击后加上的矩形, 这样不行 后来又找方法,发现在源码里,BarChartRenderer类中drawHighlighted这个方法是用来设置点击条形图选中的矩形框的 那就好办了,也改了
在SuddleBarChartRenderer类中,增加如下代码
override fun drawHighlighted(c: Canvas, indices: Array<Highlight>) {
val barData = mChart.barData
for (high in indices) {
val set = barData.getDataSetByIndex(high.dataSetIndex)
if (set == null || !set.isHighlightEnabled) continue
val e = set.getEntryForXValue(high.x, high.y)
if (!isInBoundsX(e, set)) continue
val trans = mChart.getTransformer(set.axisDependency)
mHighlightPaint.color = set.highLightColor
mHighlightPaint.alpha = set.highLightAlpha
val isStack = if (high.stackIndex >= 0 && e.isStacked) true else false
val y1: Float
val y2: Float
if (isStack) {
if (mChart.isHighlightFullBarEnabled) {
y1 = e.positiveSum
y2 = -e.negativeSum
} else {
val range = e.ranges[high.stackIndex]
y1 = range.from
y2 = range.to
}
} else {
y1 = e.y
y2 = 0f
}
prepareBarHighlight(e.x, y1, y2, barData.barWidth / 2f, trans)
setHighlightDrawPos(high, mBarRect)
val path = Path()
// path.addRoundRect(
// mBarRect,
// floatArrayOf(30f, 30f, 30f, 30f, 30f, 0f, 0f, 0f),
// Path.Direction.CCW
// )
c.drawRoundRect(mBarRect,25.toFloat(),25.toFloat(),mHighlightPaint)
// c.drawRect(mBarRect, mHighlightPaint)//源码
}
}
那么 加载一下,大功告成。