Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom position for bar values

I'm using the MPAndroidChart library to create bar charts.

We can use the following to show the bar values on top of the bar.

mChart.setDrawValueAboveBar(false);

or we can use this :

barDataSet.setDrawValues(true);

to show the bar values inside the bar itself. I want to know if we can set a custom position for the values. For example below the y-axis.

enter image description here

Solution

public class TextBarChartRenderer extends BarChartRenderer {

    public TextBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
        super(chart, animator, viewPortHandler);
    }

    @Override
    public void drawValues(Canvas c) {
        List<IBarDataSet> dataSets = mChart.getBarData().getDataSets();

        final float valueOffsetPlus = Utils.convertDpToPixel(22f)
        float negOffset;

        for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) {

            IBarDataSet dataSet = dataSets.get(i);
            applyValueTextStyle(dataSet);
            float valueTextHeight = Utils.calcTextHeight(mValuePaint, "8");
            negOffset = valueTextHeight + valueOffsetPlus;

            BarBuffer buffer = mBarBuffers[i];

            float left;
            float right;
            float top;
            float bottom;

            for (int j = 0; j < buffer.buffer.length * mAnimator.getPhaseX(); j += 4) {

                left = buffer.buffer[j];
                right = buffer.buffer[j + 2];
                top = buffer.buffer[j + 1];
                bottom = buffer.buffer[j + 3];

                float x = (left + right) / 2f;

                if (!mViewPortHandler.isInBoundsRight(x))
                    break;

                if (!mViewPortHandler.isInBoundsY(top) || !mViewPortHandler.isInBoundsLeft(x))
                    continue;

                BarEntry entry = dataSet.getEntryForIndex(j / 4);
                float val = entry.getY();

                if(val > 0) {
                    drawValue(c, dataSet.getValueFormatter(), val, entry, i, x,
                            (bottom + negOffset),
                            dataSet.getValueTextColor(j / 4));
                }
            }
        }

    }
}

Also had to add this so that the values are visible

mChart.setExtraOffsets(0, 0, 0, 20);
like image 880
sauvik Avatar asked Jan 03 '17 13:01

sauvik


People also ask

How do you describe a stacked bar chart?

A stacked bar graph (or stacked bar chart) is a chart that uses bars to show comparisons between categories of data, but with ability to break down and compare parts of a whole. Each bar in the chart represents a whole, and segments in the bar represent different parts or categories of that whole.

What is a segmented bar chart?

A segmented bar graph is a graphical representation of data in which the bars are divided into segments. The segments can be different colors, sizes, or shapes to make the data easier to understand. Segmented bar graphs are often used to compare data between other groups.

Which sets of data should a stacked bar chart be used?

The data given as different parts and cumulated volume can be easily represented using a stacked bar chart. Multiple data of gradual variation of data for a single variable can effectively visualize by this type of graph. Stacked bar charts are helpful when you want to compare the total and one part as well.


1 Answers

There is no method in the API exposed for changing the position of the value labels to below the YAxis. You will probably have to extend and modify the library to meet your uncommon requirement.

One option to try would be to implement an IAxisValueFormatter on the XAxis to render y-values instead of x-values. A simple example could re-use the existing IndexAxisValueFormatter. Let's say you have the labels for the y-values in a String [] called yLabels. You can now do this:

mChart.getXAxis().setValueFormatter(new IndexAxisValueFormatter(yLabels));

If that doesn't work, you will have to look at the source for BarChartRenderer. There is a method called drawValues() which you can override to achieve the effect you want.

So you would have something like:

public class MyBarChartRenderer extends BarChartRenderer {

    //TODO: a constructor matching the superclass

    @Override
    public void drawValues(Canvas c) {
        //TODO: copy and paste the code from the superclass and simply
        //change the offset for drawing the labels
    }
}
like image 68
David Rawson Avatar answered Oct 03 '22 12:10

David Rawson