thumbnail1

Back to Blog

Customizable DataPoint Labels

Posted on 13 May 2014 Written by Andrew Polkinghorn

A feature that is commonly asked to be added to ShinobiCharts was DataPoint Labels. Well… they are now available in the latest version of our iOS Charts! This blog post explains how easy it is to customize your own bar chart’s datapoint labels in a few simple steps.

I’m going to use a sample project which applies a custom datapoint label style to a bar chart which displays medal data from the Winter Olympics. You can browse or clone the finished project used in this post on github, or download it as a zip. You’ll need a copy of ShinobiCharts to build the project – if you don’t have one yet, you can download a free trial

Screenshot

To make datapoint labels appear you need to set the “showLabels” property on your series “dataPointLabelStyle” object to “YES” like so:

barSeries.style.dataPointLabelStyle.showLabels = YES;

This should make labels appear at the end of each bar with the text set to the X-Axis value for that datapoint.

Screen Shot 2014 05 01 At 101853

This is where we can start having a little fun!

We can now customize this datapoint label before it appears on screen. This can be done by implementing the SChartDelegate method “sChart:alterDataPointLabel:forDataPoint:inSeries:”.

Make sure you have set the delegate on your chart so your implementation of this method gets called, e.g.

self.chart.delegate = self;

In the implementation of “sChart:alterDataPointLabel:forDataPoint:inSeries:” we get passed an object of type SChartDataPointLabel which is a subclass of UILabel. This is what we’ll be customizing to revamp those datapoint labels. Before we start customizing the label we need to set the “tag” property on the label like so:

// The label identifier is used to prevent already customized labels getting customized again.
if (label.tag != LABEL_IDENTIFIER) {
    label.tag = LABEL_IDENTIFIER;
    // INSERT CUSTOM LABEL STYLE HERE
    ...
}

This is so we know which labels have already been styled, preventing your custom styles being applied to a label that has already been styled. 

The first part of the label we are going to customize in this example is the label text, we are going to append another string on to the label’s text.

label.text = [label.text stringByAppendingString:@" x"];

When we edit the text on the label we have to update the label’s size values to make sure the extra text added fits inside the label. We can do this by finding the minimum width needed for the new label text to fit on the label. This can be done with the following code:

// Calculate the size of the string label with the supplied font, and no existing constraints on size.
NSDictionary *attributes = @{NSFontAttributeName:label.font};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:label.text attributes:attributes];
CGFloat labelWidth = [attributedString boundingRectWithSize:CGSizeZero
                                                        options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                                        context:nil].size.width;

We will update the label’s frame with this newly calculated “labelWidth” after our final customization so we know how big we want the label to be.

Now we are going to add a medal image to the datapoint label using the series’ index to determine which image to use as each series is a different medal. 

// Get name of image
NSInteger seriesIndex = [[self.chart series] indexOfObject:series];
NSString *imageName;
if(seriesIndex == 0) {
    // Image source: https://www.iconfinder.com/icons/38816/ball_orange_icon
    imageName = @"bronze";
} else if(seriesIndex == 1) {
    // Image source: https://www.iconfinder.com/icons/38794/ball_grey_icon
    imageName = @"silver";
} else {
    // Image source: https://www.iconfinder.com/icons/38864/ball_yellow_icon
    imageName = @"gold";
}

Once we have the correct image name we add that image to the datapoint label. 

// Add image to dataPointLabel
UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
image.frame = CGRectMake(labelWidth, 0, IMAGE_SIZE, IMAGE_SIZE);
[label addSubview:image];

This is the final customization we are going to do on the datapoint labels so we can now update the label frame’s size because we know how big we want our datapoint labels to be.

// Update label frame's size
newLabelFrame.size.width = labelWidth + IMAGE_SIZE;
newLabelFrame.size.height = IMAGE_SIZE;

Finally, we now update the position of the datapoint label by updating the label’s origin values.

// We need to reposition the label by updating its origin values.
newLabelFrame.origin.x = CGRectGetMidX(label.frame) - (newLabelFrame.size.width + PADDING);
newLabelFrame.origin.y = CGRectGetMidY(label.frame) - newLabelFrame.size.height / 2;
label.frame = newLabelFrame;

The datapoint labels needs to be repositioned every time the chart calls this method due to it positioning the label at the end of the bar by default. 

You should now be able to see a fully customized datapoint label on your bar chart!

To summarise, here are the steps to follow to customize your dataPoint labels:

  1. Set the “showLabels” property on the “barSeries.style.dataPointLabelStyle” object to YES.
  2. Set the delegate on your chart and implement the SChartDelegate method “sChart:alterDataPointLabel:forDataPoint:inSeries:”.
  3. Set the “tag” property on the datapoint label to identify which labels need styling. 
  4. Customize the SChartDataPointLabel to your heart’s content! 

If you got stuck with any of this, you can download the finished project used in this post from github.

Back to Blog