Mpandroidchart: Different background colors for Y ranges

Created on 28 Mar 2015  路  10Comments  路  Source: PhilJay/MPAndroidChart

Do we have functionality to draw multicolor background for different Y ranges? Like in this picture.
screenshot_2015-03-28-20-56-58

Most helpful comment

Hi, this is the branch
https://github.com/mesropd/MPAndroidChart/tree/limitZone
And this is the usage

YAxis yAxis = chart.getAxisRight();
LimitZone z0 = new LimitZone(1000, (float) marketLine.highValue, Color.parseColor("#2e1227"));
LimitZone z1 = new LimitZone((float) marketLine.highValue, (float) marketLine.lowValue, Color.parseColor("#142b26"));
LimitZone z2 = new LimitZone((float) marketLine.lowValue, 0, Color.parseColor("#2e1227"));
yAxis.addLimitZone(z0);
yAxis.addLimitZone(z1);
yAxis.addLimitZone(z2);

There are merge conflicts now with the master branch, but I hope that you can merge it and this will be helpful )
Also notice that vertical seek bar and thumb is not included in this branch, it is separate views above the chart

All 10 comments

THats currently not possible! You will have to implement it yourself!

Best regards,
Phil

Hi,

I also need to do this, to paint a safe zone in a line chart. How should I go about painting specific part in the background with a custom color? I will need access to the Y axis scale and position.

Hi, this is the branch
https://github.com/mesropd/MPAndroidChart/tree/limitZone
And this is the usage

YAxis yAxis = chart.getAxisRight();
LimitZone z0 = new LimitZone(1000, (float) marketLine.highValue, Color.parseColor("#2e1227"));
LimitZone z1 = new LimitZone((float) marketLine.highValue, (float) marketLine.lowValue, Color.parseColor("#142b26"));
LimitZone z2 = new LimitZone((float) marketLine.lowValue, 0, Color.parseColor("#2e1227"));
yAxis.addLimitZone(z0);
yAxis.addLimitZone(z1);
yAxis.addLimitZone(z2);

There are merge conflicts now with the master branch, but I hope that you can merge it and this will be helpful )
Also notice that vertical seek bar and thumb is not included in this branch, it is separate views above the chart

Thanks!
I managed to write my own that suffices my requirements. Here is the code for reference.

public class DetailLineChart extends LineChart{

    protected Paint mYAxisSafeZonePaint;

    public DetailLineChart(Context context) {
        super(context);
    }

    public DetailLineChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DetailLineChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void init() {
        super.init();
        mYAxisSafeZonePaint = new Paint();
        mYAxisSafeZonePaint.setStyle(Paint.Style.FILL);
        mGridBackgroundPaint.setColor(Color.rgb(240, 240, 240));
    }

    @Override
    protected void onDraw(Canvas canvas) {

        List<LimitLine> limitLines = mAxisLeft.getLimitLines();

        if (limitLines == null || limitLines.size() != 2)
            return;

        float[] pts = new float[4];
        LimitLine l1 = limitLines.get(0);
        LimitLine l2 = limitLines.get(1);

        pts[1] = l1.getLimit();
        pts[3] = l2.getLimit();

        mLeftAxisTransformer.pointValuesToPixel(pts);

        canvas.drawRect(mViewPortHandler.contentLeft(), pts[1], mViewPortHandler.contentRight(), pts[3], mYAxisSafeZonePaint);

        super.onDraw(canvas);
    }

    public void setSafeZoneColor(int color) {
        mYAxisSafeZonePaint.setColor(color);
    }
}

@broncha , can you show me an example on how you used that class with the limits ?

YAxis leftAxis = chart.getAxisLeft();

LimitLine upperLimitLine = new LimitLine(100);
upperLimitLine.setLineColor(context.getResources().getColor(R.color.red));
leftAxis.addLimitLine(upperLimitLine);

LimitLine lowerLimitLine = new LimitLine(20);
lowerLimitLine.setLineColor(context.getResources().getColor(R.color.red));
leftAxis.addLimitLine(lowerLimitLine);

I am not able to colour a range here,for me the whole Horizontal bar chart's background is getting colored.Please guide.

Is there any chance this will be implemented in the next version?

As this is still an issue I throw in my two cents.
I tried a workaround with adding limit lines to build a zone, but I got the error message that I use too much limit lines in the plot. It seems to work anyway but I guess the performance is not optimal.

So I implemented a subclass for drawing zones in the background. Maybe it's helpful for someone:

public class TargetZoneCombinedChart extends CombinedChart {

    protected Paint mYAxisSafeZonePaint;
    private List<TargetZone> mTargetZones;

    public TargetZoneCombinedChart(Context context) {
        super(context);
    }

    public TargetZoneCombinedChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TargetZoneCombinedChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void init() {
        super.init();
        mYAxisSafeZonePaint = new Paint();
        mYAxisSafeZonePaint.setStyle(Paint.Style.FILL);
        mTargetZones = new ArrayList<>();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        for (TargetZone targetZone : mTargetZones) {
            // prepare coordinates
            float[] pts = new float[4];
            pts[1] = targetZone.lowerLimit;
            pts[3] = targetZone.upperLimit;
            mLeftAxisTransformer.pointValuesToPixel(pts);

            // draw
            mYAxisSafeZonePaint.setColor(targetZone.color);
            canvas.drawRect(mViewPortHandler.contentLeft(), pts[1], mViewPortHandler.contentRight(),
                    pts[3], mYAxisSafeZonePaint);
        }
        super.onDraw(canvas);
    }

    public void addTargetZone(TargetZone targetZone){
        mTargetZones.add(targetZone);
    }

    public List<TargetZone> getTargetZones(){
        return mTargetZones;
    }

    public void clearTargetZones(){
        mTargetZones = new ArrayList<>();
    }

    public static class TargetZone {
        public final int color;
        public final float lowerLimit;
        public final float upperLimit;

        public TargetZone(int color, float lowerLimit, float upperLimit) {
            this.color = color;
            this.lowerLimit = lowerLimit;
            this.upperLimit = upperLimit;
        }
    }
}

To add a zone you just need to add a target zone object:

float rangeHigh = 180f;
float rangeLow = 80f;

chart.addTargetZone(new TargetZoneCombinedChart.TargetZone(                Color.parseColor("#33b5eb45"),rangeLow,rangeHigh));

whereby the ranges are y values of the left axis.

Thanks, @juehv for recommending the solution. I was able to extend it and add labels for my needs

`
public class TargetZoneLineChart extends LineChart {

protected Paint mYAxisSafeZonePaint;
protected TextPaint textPaint;
private List<TargetZone> mTargetZones;

public TargetZoneLineChart(Context context) {
    super(context);
}

public TargetZoneLineChart(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public TargetZoneLineChart(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
protected void init() {
    super.init();
    mYAxisSafeZonePaint = new Paint();
    textPaint = new TextPaint();
    textPaint.setAntiAlias(true);
    textPaint.setTextSize(20 *  getResources().getDisplayMetrics().density);
    mYAxisSafeZonePaint.setStyle(Paint.Style.FILL);
    mTargetZones = new ArrayList<>();
}

@Override
protected void onDraw(Canvas canvas) {
    for (TargetZone targetZone : mTargetZones) {
        // prepare coordinates
        float[] pts = new float[4];
        pts[1] = targetZone.lowerLimit;
        pts[3] = targetZone.upperLimit;
        mLeftAxisTransformer.pointValuesToPixel(pts);

        // draw
        mYAxisSafeZonePaint.setColor(targetZone.color);
        canvas.drawRect(mViewPortHandler.contentLeft(), pts[1], mViewPortHandler.contentRight(),
                pts[3], mYAxisSafeZonePaint);
        textPaint.setColor(Color.DKGRAY);
        textPaint.setTextSize(30);
        canvas.drawText(targetZone.text,getCenter().x,pts[1] + 50,textPaint);
    }
    super.onDraw(canvas);
}

public void addTargetZone(TargetZone targetZone){
    mTargetZones.add(targetZone);
}

public List<TargetZone> getTargetZones(){
    return mTargetZones;
}

public void clearTargetZones(){
    mTargetZones = new ArrayList<>();
}

public static class TargetZone {
    public final int color;
    public final float lowerLimit;
    public final float upperLimit;
    public final String text;

    public TargetZone(int color, float lowerLimit, float upperLimit,String text) {
        this.color = color;
        this.lowerLimit = lowerLimit;
        this.upperLimit = upperLimit;
        this.text = text;
    }
}}

Usage

float rangeHigh = 180f;
float rangeLow = 80f;

chart.addTargetZone(new TargetZoneCombinedChart.TargetZone( Color.parseColor("#33b5eb45"),rangeLow,rangeHigh,"Some Text"))`

Was this page helpful?
0 / 5 - 0 ratings

Related issues

galex picture galex  路  3Comments

chathudan picture chathudan  路  3Comments

SutharRohit picture SutharRohit  路  3Comments

OnlyInAmerica picture OnlyInAmerica  路  3Comments

AiTheAnswer picture AiTheAnswer  路  3Comments