MPAndroidChart - 圆边条形图
MPAndroidChart - Round edged bar chart
我正在尝试为我的 android 应用程序使用 MPAndroidChart 创建如下图表。我无法弄清楚如何将条形图的边缘设为圆边。它总是以方边出现。
那么你能建议我应该做什么吗?
预先感谢您的帮助。
我已经实施了一个解决方案来直接在库本身上实现这一点。
首先创建一个 attrs.xml 添加一个新属性以用于您的图表视图。像这样:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="BarChart">
<attr name="radius" format="integer" />
</declare-styleable>
</resources>
然后在 BarChartRenderer 上编辑名为 drawDataSet 的方法:
protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mShadowPaint.setColor(dataSet.getBarShadowColor());
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
List<BarEntry> entries = dataSet.getYVals();
// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setBarSpace(dataSet.getBarSpace());
buffer.setDataSet(index);
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.feed(entries);
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);
}
}
}
这样做是在更改矩形而不是它的突出显示,因此请更改 drawHighlighted 方法中的这段代码:
if (mRadius > 0)
c.drawRoundRect(mBarRect, mRadius, mRadius, mHighlightPaint);
else
c.drawRect(mBarRect, mHighlightPaint);
要从 xml 文件中获取属性到此渲染器上,您还需要添加一个设置方法:
public void setRadius (int radius) {
mRadius = radius;
}
最后在BarChart对象上新建一个构造函数来抓取radius属性:
public BarChart(Context context, AttributeSet attrs) {
super(context, attrs);
mRadius = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto", "radius", 0);
((BarChartRenderer)mRenderer).setRadius(mRadius);
}
瞧!编码愉快:)
上面的答案是正确的,但是如果图表有负值,它就不起作用。
我选择了圆角矩形代码形式 this 答案。
步骤
将以下方法添加到BarChartRenderer
class
/**
* @param rect rectangle to be rounded
* @param rx radius x
* @param ry radius y
* @param tl true - for rounding top-left corner
* @param tr true - for rounding top-right corner
* @param br true - for rounding bottom-right corner
* @param bl true - for rounding bottom-left corner
* @return path
*/
private Path roundRect(RectF rect, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) {
float top = rect.top;
float left = rect.left;
float right = rect.right;
float bottom = rect.bottom;
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else {
path.rLineTo(0, -ry);
path.rLineTo(-rx, 0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else {
path.rLineTo(-rx, 0);
path.rLineTo(0, ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else {
path.rLineTo(0, ry);
path.rLineTo(rx, 0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else {
path.rLineTo(rx, 0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}
在drawDataSet(Canvas c, IBarDataSet dataSet, int index)
方法中,将所有drawRoundRect
方法替换为以下代码
Path path = roundRect(yourRect, yourRadius, yourRadius, true, true, false, false);
canvas.drawPath(path, yourPaint);
为此,您需要自定义 BarchartRenderer class...
步骤 1
制作自定义 class(如果您没有将 mpchart 添加为模块)复制粘贴 BarchartRenderer class 中的所有代码到您的自定义 class 中。
现在在您的自定义 class.....
中用我的方法替换您的 drawDataSet 方法
步骤 2
之后设置渲染到您刚刚创建的自定义 class。
用于设置渲染的 Kotlin 代码 Java 代码会有点相同。
到底享受
BarChartCustomRenderer customRenderer = BarChartCustomRenderer(mDashBoardBinding.topperChart, mDashBoardBinding.topperChart.getAnimator(), mDashBoardBinding.topperChart.getViewPortHandler());
topperChart.setRenderer(customRenderer);
drawDataSet:
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);
}
}
}
我已经根据上面的实际库(具有不同的绘图代码)创建了 class - v3.1.0-alpha
class RoundedBarChartRenderer(chart: BarDataProvider,
animator: ChartAnimator,
viewPortHandler: ViewPortHandler,
private val mRadius: Float) :
BarChartRenderer(chart, animator, viewPortHandler) {
private val mBarShadowRectBuffer = RectF()
override fun drawDataSet(c: Canvas?, dataSet: IBarDataSet?, index: Int) {
if (c == null || dataSet == null) return
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
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.drawRoundRect(mBarRect, mRadius, mRadius, mShadowPaint)
i++
}
}
// 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)
}
if (dataSet.gradientColor != null) {
val gradientColor = dataSet.gradientColor
mRenderPaint.shader = LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
gradientColor.startColor,
gradientColor.endColor,
android.graphics.Shader.TileMode.MIRROR)
}
if (dataSet.gradientColors != null) {
mRenderPaint.shader = LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
dataSet.getGradientColor(j / 4).startColor,
dataSet.getGradientColor(j / 4).endColor,
Shader.TileMode.MIRROR)
}
c.drawRoundRect(RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint)
if (drawBorder) {
c.drawRoundRect(RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mBarBorderPaint)
}
j += 4
}
}
}
我尝试组合@mallaudin 和@Janusz Hain 代码。现在可以用了,谢谢!!!
这是我的代码
public class CustomBarChartRender extends BarChartRenderer {
private RectF mBarShadowRectBuffer = new RectF();
private int mRadius;
public CustomBarChartRender(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
public void setRadius(int mRadius) {
this.mRadius = mRadius;
}
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mBarBorderPaint.setColor(dataSet.getBarBorderColor());
mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth()));
mShadowPaint.setColor(dataSet.getBarShadowColor());
boolean drawBorder = dataSet.getBarBorderWidth() > 0f;
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
if (mChart.isDrawBarShadowEnabled()) {
mShadowPaint.setColor(dataSet.getBarShadowColor());
BarData barData = mChart.getBarData();
float barWidth = barData.getBarWidth();
float barWidthHalf = barWidth / 2.0f;
float x;
int i = 0;
double count = Math.min(Math.ceil((int) (double) ((float) dataSet.getEntryCount() * phaseX)), dataSet.getEntryCount());
while (i < count) {
BarEntry e = dataSet.getEntryForIndex(i);
x = e.getX();
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.drawRoundRect(mBarRect, mRadius, mRadius, mShadowPaint);
i++;
}
}
// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setDataSet(index);
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.setBarWidth(mChart.getBarData().getBarWidth());
buffer.feed(dataSet);
trans.pointValuesToPixel(buffer.buffer);
boolean isSingleColor = dataSet.getColors().size() == 1;
if (isSingleColor) {
mRenderPaint.setColor(dataSet.getColor());
}
int 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.setColor(dataSet.getColor(j / 4));
}
if (dataSet.getGradientColor() != null) {
GradientColor gradientColor = dataSet.getGradientColor();
mRenderPaint.setShader(new LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
gradientColor.getStartColor(),
gradientColor.getEndColor(),
android.graphics.Shader.TileMode.MIRROR));
}
if (dataSet.getGradientColors() != null) {
mRenderPaint.setShader(new LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
dataSet.getGradientColor(j / 4).getStartColor(),
dataSet.getGradientColor(j / 4).getEndColor(),
Shader.TileMode.MIRROR));
}
Path path2 = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, true, true, false, false);
c.drawPath(path2, mRenderPaint);
if (drawBorder) {
Path path = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, true, true, false, false);
c.drawPath(path, mBarBorderPaint);
}
j += 4;
}
}
private Path roundRect(RectF rect, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) {
float top = rect.top;
float left = rect.left;
float right = rect.right;
float bottom = rect.bottom;
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else {
path.rLineTo(0, -ry);
path.rLineTo(-rx, 0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else {
path.rLineTo(-rx, 0);
path.rLineTo(0, ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else {
path.rLineTo(0, ry);
path.rLineTo(rx, 0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else {
path.rLineTo(rx, 0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}}
其他class:
CustomBarChartRender barChartRender = new CustomBarChartRender(barChart,barChart.getAnimator(), barChart.getViewPortHandler());
barChartRender.setRadius(20);
barChart.setRenderer(barChartRender);
根据 MPAndroidChart 的最后代码创建了完整的要点
https://gist.github.com/xanscale/e971cc4f2f0712a8a3bcc35e85325c27
1) 添加以下内容class:
public class RoundedBarChart extends BarChartRenderer {
public RoundedBarChart(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();
if(mBarBuffers!=null){
// 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){
Path path = RoundedRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2] , buffer.buffer[j + 3] , 15,15, true, true, false, false);
c.drawPath(path,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){
Path path = RoundedRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2] , buffer.buffer[j + 3] , 15,15, true, true, false, false);
c.drawPath(path,mRenderPaint);
}
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
}
}
}
public static Path RoundedRect(
float left, float top, float right, float bottom, float rx, float ry,
boolean tl, boolean tr, boolean br, boolean bl
){
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else{
path.rLineTo(0, -ry);
path.rLineTo(-rx,0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else{
path.rLineTo(-rx, 0);
path.rLineTo(0,ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else{
path.rLineTo(0, ry);
path.rLineTo(rx,0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else{
path.rLineTo(rx,0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}
}
2) 使用barChart.renderer = RoundedBarChart(barChart, barChart.animator, barChart.viewPortHandler)
您可以使用@Xan 提供的要点,如果您希望两边都圆角,您可以实施要点并提供以下 属性 到条形图视图
barChartView.axisLeft.axisMinimum = 0f;
这将使两侧变圆。
根据@duc tan 的回答,我解决了这个问题,但是他的代码没有处理 highlight.I 添加下面的代码来解决突出显示的问题。
、、、
public void drawHighlighted(Canvas c, Highlight[] indices) {
BarData barData = mChart.getBarData();
for (Highlight high : indices) {
IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
if (set == null || !set.isHighlightEnabled()) {
continue;
}
BarEntry e = set.getEntryForXValue(high.getX(), high.getY());
if (!isInBoundsX(e, set)) {
continue;
}
Transformer trans = mChart.getTransformer(set.getAxisDependency());
mHighlightPaint.setColor(set.getHighLightColor());
mHighlightPaint.setAlpha(set.getHighLightAlpha());
boolean isStack = high.getStackIndex() >= 0 && e.isStacked();
final float y1;
final float y2;
if (isStack) {
if (mChart.isHighlightFullBarEnabled()) {
y1 = e.getPositiveSum();
y2 = -e.getNegativeSum();
} else {
Range range = e.getRanges()[high.getStackIndex()];
y1 = range.from;
y2 = range.to;
}
} else {
y1 = e.getY();
y2 = 0.f;
}
prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);
setHighlightDrawPos(high, mBarRect);
Path path2 = roundRect(new RectF(mBarRect.left, mBarRect.top, mBarRect.right,
mBarRect.bottom), mRadius, mRadius, true, true, false, false);
c.drawPath(path2, mHighlightPaint);
}
}
、、、
我正在尝试为我的 android 应用程序使用 MPAndroidChart 创建如下图表。我无法弄清楚如何将条形图的边缘设为圆边。它总是以方边出现。
那么你能建议我应该做什么吗?
预先感谢您的帮助。
我已经实施了一个解决方案来直接在库本身上实现这一点。
首先创建一个 attrs.xml 添加一个新属性以用于您的图表视图。像这样:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="BarChart">
<attr name="radius" format="integer" />
</declare-styleable>
</resources>
然后在 BarChartRenderer 上编辑名为 drawDataSet 的方法:
protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mShadowPaint.setColor(dataSet.getBarShadowColor());
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
List<BarEntry> entries = dataSet.getYVals();
// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setBarSpace(dataSet.getBarSpace());
buffer.setDataSet(index);
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.feed(entries);
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);
}
}
}
这样做是在更改矩形而不是它的突出显示,因此请更改 drawHighlighted 方法中的这段代码:
if (mRadius > 0)
c.drawRoundRect(mBarRect, mRadius, mRadius, mHighlightPaint);
else
c.drawRect(mBarRect, mHighlightPaint);
要从 xml 文件中获取属性到此渲染器上,您还需要添加一个设置方法:
public void setRadius (int radius) {
mRadius = radius;
}
最后在BarChart对象上新建一个构造函数来抓取radius属性:
public BarChart(Context context, AttributeSet attrs) {
super(context, attrs);
mRadius = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto", "radius", 0);
((BarChartRenderer)mRenderer).setRadius(mRadius);
}
瞧!编码愉快:)
上面的答案是正确的,但是如果图表有负值,它就不起作用。
我选择了圆角矩形代码形式 this 答案。
步骤
将以下方法添加到
BarChartRenderer
class/** * @param rect rectangle to be rounded * @param rx radius x * @param ry radius y * @param tl true - for rounding top-left corner * @param tr true - for rounding top-right corner * @param br true - for rounding bottom-right corner * @param bl true - for rounding bottom-left corner * @return path */ private Path roundRect(RectF rect, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) { float top = rect.top; float left = rect.left; float right = rect.right; float bottom = rect.bottom; Path path = new Path(); if (rx < 0) rx = 0; if (ry < 0) ry = 0; float width = right - left; float height = bottom - top; if (rx > width / 2) rx = width / 2; if (ry > height / 2) ry = height / 2; float widthMinusCorners = (width - (2 * rx)); float heightMinusCorners = (height - (2 * ry)); path.moveTo(right, top + ry); if (tr) path.rQuadTo(0, -ry, -rx, -ry);//top-right corner else { path.rLineTo(0, -ry); path.rLineTo(-rx, 0); } path.rLineTo(-widthMinusCorners, 0); if (tl) path.rQuadTo(-rx, 0, -rx, ry); //top-left corner else { path.rLineTo(-rx, 0); path.rLineTo(0, ry); } path.rLineTo(0, heightMinusCorners); if (bl) path.rQuadTo(0, ry, rx, ry);//bottom-left corner else { path.rLineTo(0, ry); path.rLineTo(rx, 0); } path.rLineTo(widthMinusCorners, 0); if (br) path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner else { path.rLineTo(rx, 0); path.rLineTo(0, -ry); } path.rLineTo(0, -heightMinusCorners); path.close();//Given close, last lineto can be removed. return path; }
在
drawDataSet(Canvas c, IBarDataSet dataSet, int index)
方法中,将所有drawRoundRect
方法替换为以下代码Path path = roundRect(yourRect, yourRadius, yourRadius, true, true, false, false); canvas.drawPath(path, yourPaint);
为此,您需要自定义 BarchartRenderer class...
步骤 1
制作自定义 class(如果您没有将 mpchart 添加为模块)复制粘贴 BarchartRenderer class 中的所有代码到您的自定义 class 中。 现在在您的自定义 class.....
中用我的方法替换您的 drawDataSet 方法步骤 2
之后设置渲染到您刚刚创建的自定义 class。
用于设置渲染的 Kotlin 代码 Java 代码会有点相同。
到底享受
BarChartCustomRenderer customRenderer = BarChartCustomRenderer(mDashBoardBinding.topperChart, mDashBoardBinding.topperChart.getAnimator(), mDashBoardBinding.topperChart.getViewPortHandler());
topperChart.setRenderer(customRenderer);
drawDataSet:
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);
}
}
}
我已经根据上面的实际库(具有不同的绘图代码)创建了 class - v3.1.0-alpha
class RoundedBarChartRenderer(chart: BarDataProvider,
animator: ChartAnimator,
viewPortHandler: ViewPortHandler,
private val mRadius: Float) :
BarChartRenderer(chart, animator, viewPortHandler) {
private val mBarShadowRectBuffer = RectF()
override fun drawDataSet(c: Canvas?, dataSet: IBarDataSet?, index: Int) {
if (c == null || dataSet == null) return
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
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.drawRoundRect(mBarRect, mRadius, mRadius, mShadowPaint)
i++
}
}
// 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)
}
if (dataSet.gradientColor != null) {
val gradientColor = dataSet.gradientColor
mRenderPaint.shader = LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
gradientColor.startColor,
gradientColor.endColor,
android.graphics.Shader.TileMode.MIRROR)
}
if (dataSet.gradientColors != null) {
mRenderPaint.shader = LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
dataSet.getGradientColor(j / 4).startColor,
dataSet.getGradientColor(j / 4).endColor,
Shader.TileMode.MIRROR)
}
c.drawRoundRect(RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint)
if (drawBorder) {
c.drawRoundRect(RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mBarBorderPaint)
}
j += 4
}
}
}
我尝试组合@mallaudin 和@Janusz Hain 代码。现在可以用了,谢谢!!! 这是我的代码
public class CustomBarChartRender extends BarChartRenderer {
private RectF mBarShadowRectBuffer = new RectF();
private int mRadius;
public CustomBarChartRender(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
public void setRadius(int mRadius) {
this.mRadius = mRadius;
}
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mBarBorderPaint.setColor(dataSet.getBarBorderColor());
mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth()));
mShadowPaint.setColor(dataSet.getBarShadowColor());
boolean drawBorder = dataSet.getBarBorderWidth() > 0f;
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
if (mChart.isDrawBarShadowEnabled()) {
mShadowPaint.setColor(dataSet.getBarShadowColor());
BarData barData = mChart.getBarData();
float barWidth = barData.getBarWidth();
float barWidthHalf = barWidth / 2.0f;
float x;
int i = 0;
double count = Math.min(Math.ceil((int) (double) ((float) dataSet.getEntryCount() * phaseX)), dataSet.getEntryCount());
while (i < count) {
BarEntry e = dataSet.getEntryForIndex(i);
x = e.getX();
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.drawRoundRect(mBarRect, mRadius, mRadius, mShadowPaint);
i++;
}
}
// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setDataSet(index);
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.setBarWidth(mChart.getBarData().getBarWidth());
buffer.feed(dataSet);
trans.pointValuesToPixel(buffer.buffer);
boolean isSingleColor = dataSet.getColors().size() == 1;
if (isSingleColor) {
mRenderPaint.setColor(dataSet.getColor());
}
int 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.setColor(dataSet.getColor(j / 4));
}
if (dataSet.getGradientColor() != null) {
GradientColor gradientColor = dataSet.getGradientColor();
mRenderPaint.setShader(new LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
gradientColor.getStartColor(),
gradientColor.getEndColor(),
android.graphics.Shader.TileMode.MIRROR));
}
if (dataSet.getGradientColors() != null) {
mRenderPaint.setShader(new LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
dataSet.getGradientColor(j / 4).getStartColor(),
dataSet.getGradientColor(j / 4).getEndColor(),
Shader.TileMode.MIRROR));
}
Path path2 = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, true, true, false, false);
c.drawPath(path2, mRenderPaint);
if (drawBorder) {
Path path = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, true, true, false, false);
c.drawPath(path, mBarBorderPaint);
}
j += 4;
}
}
private Path roundRect(RectF rect, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) {
float top = rect.top;
float left = rect.left;
float right = rect.right;
float bottom = rect.bottom;
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else {
path.rLineTo(0, -ry);
path.rLineTo(-rx, 0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else {
path.rLineTo(-rx, 0);
path.rLineTo(0, ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else {
path.rLineTo(0, ry);
path.rLineTo(rx, 0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else {
path.rLineTo(rx, 0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}}
其他class:
CustomBarChartRender barChartRender = new CustomBarChartRender(barChart,barChart.getAnimator(), barChart.getViewPortHandler());
barChartRender.setRadius(20);
barChart.setRenderer(barChartRender);
根据 MPAndroidChart 的最后代码创建了完整的要点
https://gist.github.com/xanscale/e971cc4f2f0712a8a3bcc35e85325c27
1) 添加以下内容class:
public class RoundedBarChart extends BarChartRenderer {
public RoundedBarChart(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();
if(mBarBuffers!=null){
// 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){
Path path = RoundedRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2] , buffer.buffer[j + 3] , 15,15, true, true, false, false);
c.drawPath(path,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){
Path path = RoundedRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2] , buffer.buffer[j + 3] , 15,15, true, true, false, false);
c.drawPath(path,mRenderPaint);
}
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
}
}
}
public static Path RoundedRect(
float left, float top, float right, float bottom, float rx, float ry,
boolean tl, boolean tr, boolean br, boolean bl
){
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else{
path.rLineTo(0, -ry);
path.rLineTo(-rx,0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else{
path.rLineTo(-rx, 0);
path.rLineTo(0,ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else{
path.rLineTo(0, ry);
path.rLineTo(rx,0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else{
path.rLineTo(rx,0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}
}
2) 使用barChart.renderer = RoundedBarChart(barChart, barChart.animator, barChart.viewPortHandler)
您可以使用@Xan 提供的要点,如果您希望两边都圆角,您可以实施要点并提供以下 属性 到条形图视图
barChartView.axisLeft.axisMinimum = 0f;
这将使两侧变圆。
根据@duc tan 的回答,我解决了这个问题,但是他的代码没有处理 highlight.I 添加下面的代码来解决突出显示的问题。 、、、 public void drawHighlighted(Canvas c, Highlight[] indices) { BarData barData = mChart.getBarData();
for (Highlight high : indices) {
IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
if (set == null || !set.isHighlightEnabled()) {
continue;
}
BarEntry e = set.getEntryForXValue(high.getX(), high.getY());
if (!isInBoundsX(e, set)) {
continue;
}
Transformer trans = mChart.getTransformer(set.getAxisDependency());
mHighlightPaint.setColor(set.getHighLightColor());
mHighlightPaint.setAlpha(set.getHighLightAlpha());
boolean isStack = high.getStackIndex() >= 0 && e.isStacked();
final float y1;
final float y2;
if (isStack) {
if (mChart.isHighlightFullBarEnabled()) {
y1 = e.getPositiveSum();
y2 = -e.getNegativeSum();
} else {
Range range = e.getRanges()[high.getStackIndex()];
y1 = range.from;
y2 = range.to;
}
} else {
y1 = e.getY();
y2 = 0.f;
}
prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);
setHighlightDrawPos(high, mBarRect);
Path path2 = roundRect(new RectF(mBarRect.left, mBarRect.top, mBarRect.right,
mBarRect.bottom), mRadius, mRadius, true, true, false, false);
c.drawPath(path2, mHighlightPaint);
}
}
、、、