使用MpAndroidChart的水平条形图的负条和正条的圆角 [英] Round Corners for both Negative and Positive bars of horizontal bar chart using MpAndroidChart
问题描述
我正在尝试使水平条形图的角变圆,这是CustomChartRenderer代码:
I am trying to make the corners of horizontal bar chart rounded, here's the CustomChartRenderer code:
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) {
override fun drawDataSet(c: Canvas?, dataSet: IBarDataSet?, index: Int) {
super.drawDataSet(c, dataSet, index)
val trans = mChart.getTransformer(dataSet!!.axisDependency)
mShadowPaint.color = dataSet.barShadowColor
val phaseX = mAnimator.phaseX
val phaseY = mAnimator.phaseY
// initialize the buffer
// initialize the buffer
val buffer = mBarBuffers[index]
buffer.setPhases(phaseX, phaseY)
buffer.setDataSet(index)
buffer.setInverted(mChart.isInverted(dataSet.axisDependency))
buffer.feed(dataSet)
trans.pointValuesToPixel(buffer.buffer)
val length = buffer.buffer.size
var left = 0f
var right = 0f
val top = buffer.buffer[length - 3]
val bot = buffer.buffer[length - 1]
var leftSaved = false
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
}
// Set the color for the currently drawn value.
// If the index is
// out of bounds, reuse colors.
val color = dataSet.getColor(j / 4)
mRenderPaint.color = color
if (color != 0 && !leftSaved) {
leftSaved = true
left = buffer.buffer[j]
}
if (j > 4) { // it works but its ugly
right = buffer.buffer[j - 2]
}
c!!.drawRect(buffer.buffer[j], buffer.buffer[j + 1] + 10, buffer.buffer[j + 2],
buffer.buffer[j + 3] - 10, mRenderPaint)
j += 4
}
val erasePaint = Paint()
erasePaint.setAntiAlias(true)
erasePaint.setStyle(Paint.Style.STROKE)
val paintWidth = 20f
erasePaint.setStrokeWidth(paintWidth)
erasePaint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.CLEAR))
c!!.drawRoundRect(RectF(left - paintWidth / 2, top, right + paintWidth / 2, bot), 30f, 30f, erasePaint)
}
}
但是结果如下:
但是我想要这样:
那么我在这里做错了什么?我也已经在寻找其他线程,但是它们都没有要求对负条和正条都使用水平条形图,因此请帮助我解决此问题.
So what i am doing wrong here? I have looked for other threads too but none of them claims for horizontal bar chart for both negative and positive bars so please help me to solve this issue.
更新: 这是水平条形图的设置:
Update: Here's the settings for horizontal bar chart:
private fun setHorizontalChart(data : BarData, brand: ArrayList<String>){
horizonatal_chart.setDrawBarShadow(false)
val description = Description()
description.text = ""
horizonatal_chart.description = description
horizonatal_chart.legend.setEnabled(false)
horizonatal_chart.setPinchZoom(false)
horizonatal_chart.setDrawValueAboveBar(false)
horizonatal_chart.setScaleEnabled(false)
horizonatal_chart.setDrawValueAboveBar(true)
//Display the axis on the left (contains the labels 1*, 2* and so on)
val xAxis = horizonatal_chart.getXAxis()
xAxis.setDrawGridLines(false)
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM)
xAxis.setEnabled(true)
xAxis.setDrawAxisLine(false)
xAxis.textColor = Color.parseColor("#a1a1a1")
val yLeft = horizonatal_chart.axisLeft
//Set the minimum and maximum bar lengths as per the values that they represent
yLeft.axisMaximum = 100f
yLeft.axisMinimum = 0f
yLeft.isEnabled = false
//Now add the labels to be added on the vertical axis
xAxis.valueFormatter = IAxisValueFormatter { value, axis -> brand[value.toInt()] }
val yRight = horizonatal_chart.axisRight
yRight.setDrawAxisLine(true)
yRight.setDrawGridLines(false)
yRight.isEnabled = false
//Set bar entries and add necessary formatting
horizonatal_chart.axisLeft.setAxisMinimum(data.yMin)
data.barWidth = 0.9f
val myCustomChartRender = MyCustomChartRender(horizonatal_chart, horizonatal_chart.animator, horizonatal_chart.viewPortHandler)
//Add animation to the graph
horizonatal_chart.renderer = myCustomChartRender
horizonatal_chart.animateY(2000)
horizonatal_chart.data = data
horizonatal_chart.setTouchEnabled(false)
horizonatal_chart.invalidate()
}
推荐答案
在这里回答问题并不迟,但可能会对其他人有所帮助.我们 可以通过很少的自定义编码来实现.
It is little late to answer here but may be helpful for others. We can achieve it by little custom coding.
首先我们需要创建一个自定义类
first of all we need to create a custom class
public class RoundedHorizontalBarChartRenderer extends HorizontalBarChartRenderer {
public RoundedHorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
private float mRadius=5f;
public void setmRadius(float mRadius) {
this.mRadius = mRadius;
}
@Override
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mShadowPaint.setColor(dataSet.getBarShadowColor());
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setDataSet(index);
buffer.setBarWidth(mChart.getBarData().getBarWidth());
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.feed(dataSet);
trans.pointValuesToPixel(buffer.buffer);
// if multiple colors
if (dataSet.getColors().size() > 1) {
for (int j = 0; j < buffer.size(); j += 4) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
continue;
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;
if (mChart.isDrawBarShadowEnabled()) {
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
else
c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom(), mShadowPaint);
}
// Set the color for the currently drawn value. If the index
// is
// out of bounds, reuse colors.
mRenderPaint.setColor(dataSet.getColor(j / 4));
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
} else {
mRenderPaint.setColor(dataSet.getColor());
for (int j = 0; j < buffer.size(); j += 4) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
continue;
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;
if (mChart.isDrawBarShadowEnabled()) {
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
}
}
}
现在,在您的活动中
now, in your Activity
BarChart barchart = (BarChart) findViewById( R.id.barchart );
RoundedHorizontalBarChartRenderer roundedBarChartRenderer= new RoundedHorizontalBarChartRenderer(barchart , barchart.getAnimator(), barchart.getViewPortHandler());
roundedBarChartRenderer.setmRadius(20f);
barchart.setRenderer(roundedBarChartRenderer);
希望这会有所帮助,如果发现有帮助,请接受答案.
Hope this is helpful, please accept the answer if found helpful.
这篇关于使用MpAndroidChart的水平条形图的负条和正条的圆角的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!