Charts: [Charts 3.0] Issue with centerAxisLabelsEnabled

Created on 27 Sep 2016  Â·  12Comments  Â·  Source: danielgindi/Charts

I've used a CombinedChartView which has chartdata & linedata. The chartdata is grouped but the xAxis labels are not in center.

screen shot 2016-09-27 at 2 06 10 pm

I tried setting xAxis.centerAxisLabelsEnabled = true but the app crashed at IAxisValueFormatter

Below is the Formatter class :

class MonthChartFormatter: NSObject, IAxisValueFormatter {

    var nameValues: [String]! = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

    public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        return String(describing: nameValues![Int(value)])
    }
}

The error I got :
fatal error: Index out of range

The value was somehow -1. I've no idea what went wrong. Without centerAxisLabelsEnabled, it works fine(though xAxis labels not centered).

Below are my datasets:

â–¿ Optional<Array<IChartDataSet>>
  â–¿ some : 2 elements
    â–¿ 0 : Charts.BarChartDataSet, label: Some, 12 entries:
ChartDataEntry, x: 0.0, y 8449179.0
ChartDataEntry, x: 1.0, y 10049795.0
ChartDataEntry, x: 2.0, y 11931444.0
ChartDataEntry, x: 3.0, y 13332463.0
ChartDataEntry, x: 4.0, y 13331474.0
ChartDataEntry, x: 5.0, y 13331472.0
ChartDataEntry, x: 6.0, y 13331472.0
ChartDataEntry, x: 7.0, y 13331472.0
ChartDataEntry, x: 8.0, y 13331472.0
ChartDataEntry, x: 9.0, y 13331472.0
ChartDataEntry, x: 10.0, y 13331472.0
ChartDataEntry, x: 11.0, y 13331472.0
    â–¿ 1 : Charts.BarChartDataSet, label: Some, 12 entries:
ChartDataEntry, x: 0.0, y 9489726.0
ChartDataEntry, x: 1.0, y 11563048.0
ChartDataEntry, x: 2.0, y 3096648.0
ChartDataEntry, x: 3.0, y 35001644.0
ChartDataEntry, x: 4.0, y 17885870.0
ChartDataEntry, x: 5.0, y 13331472.0
ChartDataEntry, x: 6.0, y 13331472.0
ChartDataEntry, x: 7.0, y 13331472.0
ChartDataEntry, x: 8.0, y 13331472.0
ChartDataEntry, x: 9.0, y 13331472.0
ChartDataEntry, x: 10.0, y 13331472.0
ChartDataEntry, x: 11.0, y 13331472.0

What could be the issue? Any help is much appreciated. @liuxuan30 @danielgindi

Most helpful comment

Just want to share my experience, I solved this issue using a dynamic granularity, make chart adjust while zooming

Important do not force labelCount

First I have many datasets, so I group datasets values using

let groupSpace = 0.4
let barSpace = 0.03
let barWidth = 0.2

data.barWidth = barWidth

chart.xAxis.axisMinimum = 0.0
chart.xAxis.axisMaximum = 0.0 + data.groupWidth(groupSpace: groupSpace, barSpace: barSpace) * Double(labels.count)

data.groupBars(fromX: 0.0, groupSpace: groupSpace, barSpace: barSpace)

Adjust granularity base on how many columns you want to see
chart.xAxis.granularity = chart.xAxis.axisMaximum / Double(labels.count)

Then set data
chart.data = data

Then I use a custom Formatter to calculate label to be shown

class CustomLabelsAxisValueFormatter : NSObject, IAxisValueFormatter {

    var labels: [String] = []

    func stringForValue(_ value: Double, axis: AxisBase?) -> String {

        let count = self.labels.count

        guard let axis = axis, count > 0 else {

            return ""
        }

        let factor = axis.axisMaximum / Double(count)

        let index = Int((value / factor).rounded())

        if index >= 0 && index < count {

            return self.labels[index]
        }

        return ""
    }
}

Set the custom formatter

let formatter = CustomLabelsAxisValueFormatter()
formatter.labels = xVals
chart.xAxis.valueFormatter = formatter

Try and let me know. Happy coding!

All 12 comments

where do you get fatal error: Index out of range?

BTW, I checked combined chart in ChartsDemo on master; it works fine with centerAxisLabelsEnabled turned on.

@liuxuan30 I got the error from MonthChartFormatter class.

Oh then how would I center the labels?

I checked combined chart in ChartsDemo on master; it works fine with centerAxisLabelsEnabled turned on. Looks like you did not setup correctly; check the demo.
Look carefully about the order of setting up chart data; it matters. Ideally chart.data = data should be the last line of setting up chart

MonthChartFormatter seems your own class? Then you need to debug a little.. no idea
The demo also uses Month, so probably you check your formatter with Demo's

- (NSString *)stringForValue:(double)value
                        axis:(ChartAxisBase *)axis
{
    return months[(int)value % months.count];
}

this is now Demo passes the string to x axis. If you seeing out of range.. maybe time to use mod. I do see you use return String(describing: nameValues![Int(value)]) directly. Smell like classic out of range

@liuxuan30 Thanks a lot for looking into the issue.

This is how I'm setting up the chartView

let xAxis = combinedChartView.xAxis
        xAxis.enabled = true
        xAxis.labelPosition = .bottom
        xAxis.drawAxisLineEnabled = true
        xAxis.drawGridLinesEnabled = false
        xAxis.granularity = 1
        xAxis.avoidFirstLastClippingEnabled = true
        xAxis.centerAxisLabelsEnabled = true

        let formatter = MonthChartFormatter.init()
        xAxis.valueFormatter = formatter
        xAxis.labelCount = 12

I just logged the ChartFormatter class and this is what I got :

VALUE *** 0.0
VALUE *** 1.0
VALUE *** 2.0
VALUE *** 3.0
VALUE *** 4.0
VALUE *** 5.0
VALUE *** 6.0
VALUE *** 7.0
VALUE *** 8.0
VALUE *** 9.0
VALUE *** 10.0
VALUE *** 11.0
VALUE *** -1.0
VALUE *** 0.0
VALUE *** 1.0
VALUE *** 2.0
VALUE *** 3.0
VALUE *** 4.0
VALUE *** 5.0
VALUE *** 6.0
VALUE *** 7.0
VALUE *** 8.0
VALUE *** 9.0
VALUE *** 10.0
VALUE *** 11.0
VALUE *** 12.0
VALUE *** 0.0
VALUE *** 1.0
VALUE *** 2.0
VALUE *** 3.0
VALUE *** 4.0
VALUE *** 5.0
VALUE *** 6.0
VALUE *** 7.0
VALUE *** 8.0
VALUE *** 9.0
VALUE *** 10.0

I've no idea why is this getting called so many times when centerAxisLabelsEnabled turned on.

I tried with months[(int)value % months.count]. Same problem.

@liuxuan30 I think the entries array is generating a **value of -1**from somewhere.

Because from AxisBase.getFormattedLabel(Int) -> String, when I print out the entries its coming as :

â–¿ 14 elements
  - 0 : -1.0
  - 1 : 0.0
  - 2 : 1.0
  - 3 : 2.0
  - 4 : 3.0
  - 5 : 4.0
  - 6 : 5.0
  - 7 : 6.0
  - 8 : 7.0
  - 9 : 8.0
  - 10 : 9.0
  - 11 : 10.0
  - 12 : 11.0
  - 13 : 12.0

Phew. Found the issue. My bad. I was not setting the axisMinimum & axisMaximum & granularity set to 1. It works. Thanks a lot

Just want to share my experience, I solved this issue using a dynamic granularity, make chart adjust while zooming

Important do not force labelCount

First I have many datasets, so I group datasets values using

let groupSpace = 0.4
let barSpace = 0.03
let barWidth = 0.2

data.barWidth = barWidth

chart.xAxis.axisMinimum = 0.0
chart.xAxis.axisMaximum = 0.0 + data.groupWidth(groupSpace: groupSpace, barSpace: barSpace) * Double(labels.count)

data.groupBars(fromX: 0.0, groupSpace: groupSpace, barSpace: barSpace)

Adjust granularity base on how many columns you want to see
chart.xAxis.granularity = chart.xAxis.axisMaximum / Double(labels.count)

Then set data
chart.data = data

Then I use a custom Formatter to calculate label to be shown

class CustomLabelsAxisValueFormatter : NSObject, IAxisValueFormatter {

    var labels: [String] = []

    func stringForValue(_ value: Double, axis: AxisBase?) -> String {

        let count = self.labels.count

        guard let axis = axis, count > 0 else {

            return ""
        }

        let factor = axis.axisMaximum / Double(count)

        let index = Int((value / factor).rounded())

        if index >= 0 && index < count {

            return self.labels[index]
        }

        return ""
    }
}

Set the custom formatter

let formatter = CustomLabelsAxisValueFormatter()
formatter.labels = xVals
chart.xAxis.valueFormatter = formatter

Try and let me know. Happy coding!

@samueleperricone computing granularity worked. Cheers :)

computing granularity as done by @codingspark worked for me.

chart.xAxis.granularity = chart.xAxis.axisMaximum / Double(labels.count)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

newbiebie picture newbiebie  Â·  3Comments

kirti0525 picture kirti0525  Â·  3Comments

coop44483 picture coop44483  Â·  3Comments

guoyutaog picture guoyutaog  Â·  3Comments

deepumukundan picture deepumukundan  Â·  3Comments