Search code examples
androidandroid-graphview

Background for each series GraphView


Im using Graphview and work fine, but now i have a problem.

I would like to have a background for each series that is added to the graph, and not for all series

Is this possible?


Solution

  • This is currently (5 August 2014) not possible on the original GraphView library.

    I needed this functionality, so I forked the library and implemented the functionality myself. You can find the updated code on the feature/series_specific_styles branch of my fork:

    Hopefully in future these changes will be pulled into the original library.


    The actual code changes are relatively simple.

    • Added required background fields to GraphViewSeries.GraphViewSeriesStyle

    • Updated LineGraphView.drawSeries() to look for these fields instead of relying on its own internal values.

    I have included full updates below, but the easiest way to view them is on the commit page:


    Here is the updated GraphViewSeriesStyle class:

    static public class GraphViewSeriesStyle {
        public int color = 0xff0077cc;
        public int thickness = 3;
        private ValueDependentColor valueDependentColor;
    
        private final Paint paintBackground;
        private boolean drawBackground;
        private boolean drawDataPoints;
        private float dataPointsRadius = 10f;
    
        public GraphViewSeriesStyle() {
            super();
    
            paintBackground = new Paint();
            paintBackground.setColor(Color.rgb(20, 40, 60));
            paintBackground.setStrokeWidth(4);
            paintBackground.setAlpha(128);
        }
    
        public GraphViewSeriesStyle(int color, int thickness) {
            super();
            this.color = color;
            this.thickness = thickness;
    
            paintBackground = new Paint();
            paintBackground.setColor(Color.rgb(20, 40, 60));
            paintBackground.setStrokeWidth(4);
            paintBackground.setAlpha(128);
        }
    
        public ValueDependentColor getValueDependentColor() {
            return valueDependentColor;
        }
    
        /**
         * the color depends on the value of the data.
         * only possible in BarGraphView
         * @param valueDependentColor
         */
        public void setValueDependentColor(ValueDependentColor valueDependentColor) {
            this.valueDependentColor = valueDependentColor;
        }
    
        public boolean getDrawBackground() {
            return drawBackground;
        }
    
        public void setDrawBackground(boolean drawBackground) {
            this.drawBackground = drawBackground;
        }
    
        public Paint getPaintBackground() {
            return paintBackground;
        }
    
        public int getBackgroundColor() {
            return paintBackground.getColor();
        }
    
        /**
         * sets the background colour for the series. This is not the background
         * colour of the whole graph.
         */
        public void setBackgroundColor(int color) {
            paintBackground.setColor(color);
        }
    
        public float getDataPointsRadius() {
            return dataPointsRadius;
        }
    
        public boolean getDrawDataPoints() {
            return drawDataPoints;
        }
    
        /**
         * sets the radius of the circles at the data points.
         * @see #setDrawDataPoints(boolean)
         * @param dataPointsRadius
         */
        public void setDataPointsRadius(float dataPointsRadius) {
            this.dataPointsRadius = dataPointsRadius;
        }
    
        /**
         * You can set the flag to let the GraphView draw circles at the data points
         * @see #setDataPointsRadius(float)
         * @param drawDataPoints
         */
        public void setDrawDataPoints(boolean drawDataPoints) {
            this.drawDataPoints = drawDataPoints;
        }
    }
    

    Here is the updated LineGraphView.drawSeries() method:

    public void drawSeries(Canvas canvas, GraphViewDataInterface[] values, float graphwidth, float graphheight, float border, double minX, double minY, double diffX, double diffY, float horstart, GraphViewSeriesStyle style) {
        // draw background
        double lastEndY = 0;
        double lastEndX = 0;
    
        // draw data
        paint.setStrokeWidth(style.thickness);
        paint.setColor(style.color);
    
    
        Path bgPath = null;
        if ((drawBackground) || (style.getDrawBackground())) {
            bgPath = new Path();
        }
    
        lastEndY = 0;
        lastEndX = 0;
        float firstX = 0;
        for (int i = 0; i < values.length; i++) {
            double valY = values[i].getY() - minY;
            double ratY = valY / diffY;
            double y = graphheight * ratY;
    
            double valX = values[i].getX() - minX;
            double ratX = valX / diffX;
            double x = graphwidth * ratX;
    
            if (i > 0) {
                float startX = (float) lastEndX + (horstart + 1);
                float startY = (float) (border - lastEndY) + graphheight;
                float endX = (float) x + (horstart + 1);
                float endY = (float) (border - y) + graphheight;
    
                // draw data point
                if (drawDataPoints) {
                    //fix: last value was not drawn. Draw here now the end values
                    canvas.drawCircle(endX, endY, dataPointsRadius, paint);
                } else if (style.getDrawDataPoints()) {
                    canvas.drawCircle(endX, endY, style.getDataPointsRadius(), paint);
                }
    
                canvas.drawLine(startX, startY, endX, endY, paint);
                if (bgPath != null) {
                    if (i==1) {
                        firstX = startX;
                        bgPath.moveTo(startX, startY);
                    }
                    bgPath.lineTo(endX, endY);
                }
            } else if ((drawDataPoints) || (style.getDrawDataPoints())) {
                //fix: last value not drawn as datapoint. Draw first point here, and then on every step the end values (above)
                float first_X = (float) x + (horstart + 1);
                float first_Y = (float) (border - y) + graphheight;
                if (drawDataPoints) {
                    canvas.drawCircle(first_X, first_Y, dataPointsRadius, paint);
                } else if (style.getDrawDataPoints()) {
                    canvas.drawCircle(first_X, first_Y, style.getDataPointsRadius(), paint);
                }
            }
            lastEndY = y;
            lastEndX = x;
        }
    
        if (bgPath != null) {
            // end / close path
            bgPath.lineTo((float) lastEndX, graphheight + border);
            bgPath.lineTo(firstX, graphheight + border);
            bgPath.close();
            if (style.getDrawBackground()) {
                canvas.drawPath(bgPath, style.getPaintBackground());
            } else {
                canvas.drawPath(bgPath, paintBackground);
            }
        }
    }
    

    For interest, that branch also allows data points to be configured for each series - code changes visible here: