0

This is a 3 part question.

1) First, is it possible to rotate the horizontal X values. Currently when I am trying to display all the days in a month on the X axis (4/1/2015, 4/2/2015, etc...) they will all bunch up and become unreadable. Is there a way to rotate the X-axis labels so they are vertical?


2) To setup the viewport, the documentation suggests to use:

graphview.getViewport().setScalable(true);
graphview.getViewport().setScrollable(true);

// To set a fixed manual viewport use this:
// set manual X bounds
graph.getViewport().setXAxisBoundsManual(true);
graph.getViewport().setMinX(0.5);
graph.getViewport().setMaxX(3.5);

// set manual Y bounds
graph.getViewport().setYAxisBoundsManual(true);
graph.getViewport().setMinY(3.5);
graph.getViewport().setMaxY(8);

However, the getViewport().setMinX(...) function requires a double, not a date. Is there a way to scroll the viewport to show 3-5 dates at a time?

enter image description here

Code 2):

GraphView graph = (GraphView) graphView.findViewById(R.id.graph);

DataPoint[] stockArr = new DataPoint[dplist.size()];
stockArr = dplist.toArray(stockArr);

LineGraphSeries<DataPoint> series = new LineGraphSeries<DataPoint>(stockArr);
graph.addSeries(series);
graph.setTitle("TEST GRAPH");

// set date label formatter
graph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(context));

graph.getViewport().setScalable(true);
graph.getViewport().setScrollable(true);
graph.getGridLabelRenderer().setNumHorizontalLabels(data.size()-1); // Approx 28-30

graph.getViewport().setXAxisBoundsManual(true);
graph.getViewport().setMinX(firstDate.getTime());
graph.getViewport().setMaxX(lastDate.getTime());

3) Is there a way to line up the bullet points with the Date labels? I modified my X labels with the following code. However, even before the change it seems like the bullet points are not lined up. In the picture below, 1/1 should be the first point, 1/2 should be the 2nd point, and 1/3 should be the third point. Any ideas?

enter image description here

Code 3):

graph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(context) {

    @Override
    public String formatLabel(double value, boolean isValueX) {
        if (isValueX) {
            // show normal x values
            Calendar c = Calendar.getInstance();
            // set time in milliseconds
            c.setTimeInMillis(((long)value));
            int mYear = c.get(Calendar.YEAR);
            int mMonth = c.get(Calendar.MONTH);
            int mDay = c.get(Calendar.DAY_OF_MONTH);

            System.out.println((mMonth+1) + "/" + mDay);
            // Return Month/Day
            return (mMonth+1) + "/" + mDay;
            //return super.formatLabel(newDate.toString(), isValueX);
        } else {
            // show currency for y values
            return super.formatLabel(value, isValueX);
        }
    }
});
lcnicolau
  • 3,252
  • 4
  • 36
  • 53
koala123
  • 13
  • 1
  • 5

2 Answers2

3

1) rotated labels are currently not supported. There is already an issue for that, but I can not say when this will be implemented. You can watch it here: https://github.com/jjoe64/GraphView/issues/293

If you want to implement it for yourself you will have do this at this point of code - it should be relativ easy: https://github.com/jjoe64/GraphView/blob/master/src/main/java/com/jjoe64/graphview/GridLabelRenderer.java#L934

2) The viewport needs a double and if you want to use Dates, you have to convert the date to the unix time epoch in millis via date.getTime().

If I understand you, you want to display a timespan of 3 days at a time. So you have to set the number of horizontal labels to 3 and the viewport to a size of 3 days. Should be done like that:

graph.getViewport().setXAxisBoundsManual(true);
graph.getGridLabelRenderer().setNumHorizontalLabels(3);
graph.getViewport().setMinX(firstDate.getTime());
graph.getViewport().setMaxX(firstDate.getTime() + 3*24*60*60*1000); // + 3 days
appsthatmatter
  • 6,347
  • 3
  • 36
  • 40
  • Hi jjoe64. I implemented changes specified in your 2) response. The window does show 3 now and seems to be working great. I put a 3rd question if you can look at it. It deals with lining up the points with their labels. – koala123 Feb 21 '15 at 23:53
  • the bullet points are at the position of your input data and are not aligned to the grid – appsthatmatter Feb 26 '15 at 14:34
1

Late, but adding some light to the matter:

1) Although the issue for "x labels rendered at an angle" remains open, now it is possible.

Tested with GraphView 4.2.2. Assuming graph is your GraphView object:

graph.getGridLabelRenderer().setHorizontalLabelsAngle(90);

In some case, an angle of 135° allows to display the labels in a more compact and elegant way.


2) Look at @appsthatmatter's answer.

If you go ahead with point 3), you must adapt the @appsthatmatter's answer acording with the last part of 3): "And if you want to specify a fixed size of the viewport..."

graph.getGridLabelRenderer().setNumHorizontalLabels(3);
graph.getViewport().setXAxisBoundsManual(true);
graph.getViewport().setMinX(getDaysSinceEpoch(firstDate));
graph.getViewport().setMaxX(getDaysSinceEpoch(firstDate) + 3); // + 3 days

3) As you want to display the days in a month on the X axis (4/1/2015, 4/2/2015, etc...), I recommend you to use the number of days since Epoch, instead of milliseconds like the java.util.Date#getTime() returns. So there are no intermediate values ​​between the data to be represented.

This implies that:

  • You can't initialize a DataPoint using:

    new DataPoint(date, value);
    

    Instead, you should use something like this:

    new DataPoint(getDaysSinceEpoch(date), value);
    

    Where getDaysSinceEpoch(...) receives a date and returns the number of days since January 1, 1970, 00:00:00 GMT (Epoch) represented by this Date object. Using Joda Time:

    private int getDaysSinceEpoch(Date date) {
        return Days.daysBetween(new LocalDate(0), new LocalDate(date.getTime())).getDays();
    }
    
  • You can't use DateAsXAxisLabelFormatter.

    Instead, you must implement your own LabelFormatter:

    graph.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter() {
        @Override
        public String formatLabel(double value, boolean isValueX) {
            return isValueX
                    ? getFormattedDate((int) value, "M/d")
                    : super.formatLabel(value, isValueX);
        }
    });
    

    Where getFormattedDate(...) receives the number of days since Epoch, as well as the pattern describing the date format, and return the formatted date. Using Joda Time:

    private String getFormattedDate(int daysSinceEpoch, String pattern) {
        return new LocalDate(0).plusDays(daysSinceEpoch).toString(pattern);
    }
    
  • You should not disable the "rounding of the bounds to nice human-readable numbers" feature as Use dates as labels suggests.

    Set it true, comment or simply delete this line:

    // graph.getGridLabelRenderer().setHumanRounding(false);
    
  • And if you want to specify a fixed size of the viewport, using:

    graph.getViewport().setMinX(...);
    graph.getViewport().setMaxX(...);
    

    You can't convert the date to the number of milliseconds since Epoch using date.getTime().

    Instead, you must use the getDaysSinceEpoch(...) functionality described above.

lcnicolau
  • 3,252
  • 4
  • 36
  • 53