Charts: Custom Y Value Formatter

Created on 12 Apr 2016  路  11Comments  路  Source: danielgindi/Charts

First of all, this IOS Library is awesome! Thanks.

I have to display Y values in a BarChart in time format (mn:ss)

I have seen on the IOS documentation that a class called "ChartDefaultXAxisValueFormatter", but I can not find a way to use it.

Have anyone achieved such a thing?

Alexis

feature

Most helpful comment

I achieved it by inheriting IAxisValueFormatter .

import Foundation
import Charts
class YAxisValueFormatter: NSObject, IAxisValueFormatter {

    let numFormatter: NumberFormatter

    override init() {
        numFormatter = NumberFormatter()
        numFormatter.minimumFractionDigits = 1
        numFormatter.maximumFractionDigits = 1

        // if number is less than 1 add 0 before decimal
        numFormatter.minimumIntegerDigits = 1 // how many digits do want before decimal
        numFormatter.paddingPosition = .beforePrefix
        numFormatter.paddingCharacter = "0"
    }

    /// Called when a value from an axis is formatted before being drawn.
    ///
    /// For performance reasons, avoid excessive calculations and memory allocations inside this method.
    ///
    /// - returns: The customized label that is drawn on the axis.
    /// - parameter value:           the value that is currently being drawn
    /// - parameter axis:            the axis that the value belongs to
    ///

    public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        return numFormatter.string(from: NSNumber(floatLiteral: value))!
    }
}

create YAxisValueFormatterclass, and assign object to graph leftAxis

    // Number formatting of YAxis
    chartView.leftAxis.valueFormatter = YAxisValueFormatter()

All 11 comments

Have you looked at the example for stacked bar chart view controller? I imagine it is similar where you pass a formatter?

        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        formatter.maximumFractionDigits = 1;
        formatter.negativeSuffix = @" $";
        formatter.positiveSuffix = @" $";

        BarChartData *data = [[BarChartData alloc] initWithXVals:xVals dataSets:dataSets];
        [data setValueFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:7.f]];
        [data setValueFormatter:formatter];

        _chartView.data = data;

@dxclancy pointed it out. Be aware it's a number formatter right now, so you may need write some code to bridge the number and date formatter.

Hi there,

Thanks your answer. Unfortunately, leftAxis.valueformatter only accepts NSNumberFormatter.

I am trying to use the ChartDefaultXAxisValueFormatter as in the swift files, but I cannot manage to implement it.

What is need is to display the left(Y) axis as time ex = 1:02:58

Alexis

Hi, I assume what you want is to pass an NSDateFormatter?

I see this in the definition:
public var valueFormatter: ChartXAxisValueFormatter?

So you need to have one of your classes implement that protocol

@interface MyChartViewController: < ChartXAxisValueFormatter>

or

@interface MyCustomFormatter: NSObject < ChartXAxisValueFormatter>

or the swift equivalent.

But it sounds like you want to format the yVals, which means you only have access to a NSNumberFormatter. Right?

We are actually having a discussion about a similar issue to this in #742. However, @danielgindi 's position currently seems to be that this is incorrect.

So I think you have 3 options.

  • If ChartXAxisValueFormatter is sufficient, implement the protocol. I can help you with that.
  • If not, the simplest thing to do is to write a subclass of NSNumberFormatter that overrides stringFromNumber and pass that value to an NSDateFormatter, or perform you own custom formatting.
  • If you feel comfortable modifying the library, you can merge the pull request in #742 to your own fork and pass an NSDateFormatter, which I think will be able to format time as you wish. Or you can add a ChartYAxisValueFormatter modeled on the ChartXAxisValueFormatter.

Note that I'm fairly new to this wonderful library which has a lot of great options I'm unfamiliar with, so I may be missing something obvious.

your suggestions are appreciated. We need to think carefully if we want to move the axis formatter to formatters. Thinking that all the data is naturally numbers, we think number formatter is the formatter to use. In case you want to display different strings from the value, you can customize your own. But the formatter's source is number for sure.

I used the override method. It worked like a charm!
Thank you guys, you are the best :)

NSNumberFormatter is more correct than NSFormatter simply due to the fact that the value being passed in is _always_ a number. You don't gain anything by using NSFormatter specifically. The fact that you want an output that's not a number, does not change the fact that the input is a number, and you want to format that number in a very special manner.

We will, however, move forward with having our own interface which passes more information along with the value (the ChartYAxisValueFormatter approach).

Having said that - this issue should stay open until we implement the protocol for a Y axis value formatter.

Implemented in Charts 3.0 (v3 branch)

I achieved it by inheriting IAxisValueFormatter .

import Foundation
import Charts
class YAxisValueFormatter: NSObject, IAxisValueFormatter {

    let numFormatter: NumberFormatter

    override init() {
        numFormatter = NumberFormatter()
        numFormatter.minimumFractionDigits = 1
        numFormatter.maximumFractionDigits = 1

        // if number is less than 1 add 0 before decimal
        numFormatter.minimumIntegerDigits = 1 // how many digits do want before decimal
        numFormatter.paddingPosition = .beforePrefix
        numFormatter.paddingCharacter = "0"
    }

    /// Called when a value from an axis is formatted before being drawn.
    ///
    /// For performance reasons, avoid excessive calculations and memory allocations inside this method.
    ///
    /// - returns: The customized label that is drawn on the axis.
    /// - parameter value:           the value that is currently being drawn
    /// - parameter axis:            the axis that the value belongs to
    ///

    public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        return numFormatter.string(from: NSNumber(floatLiteral: value))!
    }
}

create YAxisValueFormatterclass, and assign object to graph leftAxis

    // Number formatting of YAxis
    chartView.leftAxis.valueFormatter = YAxisValueFormatter()

When I inherit IAxisValueFormatter as stated above, I get an error: "No type or protocol named 'IChartAxisValueFormatter'" in my ProjectName-Swift.h file.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anhltse03448 picture anhltse03448  路  3Comments

valeIT picture valeIT  路  3Comments

PrashantKT picture PrashantKT  路  3Comments

kirti0525 picture kirti0525  路  3Comments

BrandonShega picture BrandonShega  路  4Comments