MPAndroidChart - Round edged bar chart

I've implemented a solution to achieve that straight on the library itself.

Firstly create an attrs.xml adding a new attribute to use on your chart view. Something like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="BarChart">
        <attr name="radius" format="integer" />
    </declare-styleable>
</resources>

Then edit the method called drawDataSet on the BarChartRenderer:

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);
        }
    }
}

By doing this you're changing the rectangle but not its highlight, so change this bit of code on the drawHighlighted method:

if (mRadius > 0)
      c.drawRoundRect(mBarRect, mRadius, mRadius, mHighlightPaint);
else
      c.drawRect(mBarRect, mHighlightPaint);

To get the attribute from the xml file onto this render you need to add a set method as well:

public void setRadius (int radius) {
        mRadius = radius;
}

Finally create a new constructor on the BarChart object to grab the radius attribute:

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);
    }

And voila! Happy coding :)


created a complete gist from last code of MPAndroidChart

https://gist.github.com/xanscale/e971cc4f2f0712a8a3bcc35e85325c27


I try combined @mallaudin and @Janusz Hain code. It's working now, Thanks you!!! here's my code

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;
}}

In other class:

CustomBarChartRender barChartRender = new CustomBarChartRender(barChart,barChart.getAnimator(), barChart.getViewPortHandler());
    barChartRender.setRadius(20);
    barChart.setRenderer(barChartRender);