Bar Graph

This is a custom bar graph written in Objective-C using a standard UIView as the base class. The Graph is rendered inside an overloaded drawRect function using CGContext to render the graph and all it’s components.

Features:
• Positive Graph Rendering.
• Positive / Negative Graph Rendering.
• Customizable Bar rendering.
• Customizable Graph area rendering.
• Background Image support.
• Font selection.
• Hide / Show Labels.
• Hide / Show bar names.
• Hide / Show Scale.
• Hide / Show Bar Percentages.
Samples:

BarGraphPic1BarGraphPic0

Improvements and Additions:
• The drawRect function needs to be split up, it’s to big but it is a first pass implementation.
• The graph code needs to be improved to support totally negative graph values.
• I would like to add Support for different graph rendering, a sudo 3D would be nice. I think these would be provided using an enum rather than using lots of Boolean values like the current implementation.
Warning’s :
• Watch the length of your string’s and font size’s as the current implementation does not re-size fonts and these may overlap.
• I don’t recommend this implementation if you wish to animate the graph, I’ve fond that causing the view to redraw is expensive.
Source:
//
//  BarGraph.h
//
//  Created by Robert on 11/10/2009.
//

#import <UIKit/UIKit.h>

// --------------------------------------------------------
// The Bar Object
// --------------------------------------------------------
@interface Bar : NSObject
{
@private
NSString *	name;
float		value;
UIColor *	color;
}

- (id) initWithName:(NSString*)_name AndColor:(UIColor*)_color AndValue:(float)_value;

@property (nonatomic, readonly) NSString *	name;
@property (nonatomic)           float		value;
@property (nonatomic, retain)   UIColor *	color;

@end

// --------------------------------------------------------
// Bar Graph View
//
// After Adding or updating values please use the function
// setNeedsDisplay to cause the view to re-draw.
// --------------------------------------------------------
@interface BarGraph : UIView
{
@private

// --------------------------------
// Background Image :
// will be rendered if not nil.
// --------------------------------
UIImage *		 backgroundImage;
// --------------------------------

// --------------------------------
// Data Array :
// Contains the bar objects.
// --------------------------------
NSMutableArray * values;

NSString *		 verticalAxisName;
NSString *		 horizontalAxisName;
// --------------------------------

// --------------------------------
// Graph Indent :
// How much away from the edges
// does the graph get rendered.
// --------------------------------
CGSize			indent;
UIFont *		font;
UIFont *		fontSmall;
UIColor	*		fontColor;
// --------------------------------

// --------------------------------
// line settings :
// --------------------------------
NSInteger		lineWidth;
UIColor *		lineColor;
// --------------------------------

// --------------------------------
// grid data
// --------------------------------
NSInteger		gridLineWidth;
UIColor *		gridLineColor;
// --------------------------------

// --------------------------------
// Fill data
// --------------------------------
UIColor *		fillColor;
// --------------------------------

// --------------------------------
// bar layout values
// --------------------------------
NSInteger		barSeperator;
NSInteger		barVerticalIndent;

NSInteger		barOutlineWidth;
UIColor *		barOutlineColor;

float			barHighlightPercentage;
UIColor *		barHighlightColor;

CGPoint			barShadowOffset;
UIColor *		barShadowColor;
// --------------------------------

// --------------------------------
// Render Flags :
// Indicate the parts of the bar
// to render.
// --------------------------------
Boolean			drawBarHighlight;
Boolean			drawBarOutline;
Boolean			drawBarShadow;
Boolean			drawBarPercentages;
Boolean			drawBarNames;
Boolean			drawGrid;
Boolean			drawEdge;
Boolean			drawLine;
Boolean			drawFill;
Boolean			drawLabels;
Boolean			drawScale;
// --------------------------------
}

@property (nonatomic, readonly)	NSInteger count;

@property (nonatomic, retain)	UIImage * backgroundImage;
@property (nonatomic, copy)		NSString * verticalAxisName;
@property (nonatomic, copy)		NSString * horizontalAxisName;

@property (nonatomic)			CGSize indent;
@property (nonatomic, retain)	UIFont * font;
@property (nonatomic, retain)	UIFont * fontSmall;
@property (nonatomic, retain)	UIColor	* fontColor;
@property (nonatomic)			NSInteger lineWidth;
@property (nonatomic, retain)	UIColor * lineColor;
@property (nonatomic)			NSInteger gridLineWidth;
@property (nonatomic, retain)	UIColor * gridLineColor;
@property (nonatomic, retain)	UIColor * fillColor;
@property (nonatomic)			NSInteger barSeperator;
@property (nonatomic)			NSInteger barVerticalIndent;
@property (nonatomic)			NSInteger barOutlineWidth;
@property (nonatomic, retain)	UIColor * barOutlineColor;
@property (nonatomic)			float barHighlightPercentage; // 0 - 1 value;
@property (nonatomic, retain)	UIColor * barHighlightColor;
@property (nonatomic)			CGPoint barShadowOffset;
@property (nonatomic, retain)	UIColor * barShadowColor;

@property (nonatomic)			Boolean drawBarHighlight;
@property (nonatomic)			Boolean drawBarOutline;
@property (nonatomic)			Boolean drawBarShadow;
@property (nonatomic)			Boolean drawBarPercentages;
@property (nonatomic)			Boolean drawBarNames;
@property (nonatomic)			Boolean drawGrid;
@property (nonatomic)			Boolean drawEdge;
@property (nonatomic)			Boolean drawLine;
@property (nonatomic)			Boolean	drawFill;
@property (nonatomic)			Boolean drawLabels;
@property (nonatomic)			Boolean drawScale;

// remove all the current bars
- (void) removeAllBars;
- (void) removeBarAtIndex:(NSInteger)_index;
- (void) removeBarWithName:(NSString*)_name;
- (void) removeBar:(Bar*)_bar;

// add a bar
- (Bar*) addBarWithName:(NSString*)_name WithColor:(UIColor*)_color AndValue:(float)_value;

// retrieve the bar
- (Bar*) barAtIndex:(NSInteger)_index;
- (Bar*) barWithName:(NSString*)_name;

@end
// --------------------------------------------------------

The code is provided as is, use at your own risk.

Source Code : BarGraph.h, BarGraph.m

Sample Project : BarGraphSample

  1. srinivas
    May 24th, 2010 at 10:26 | #1

    i want stacked barchart coding plz send it to my mail

  2. MIK
    May 31st, 2010 at 08:03 | #2

    Hi, dear
    i stuck in bar graph chart. can i forward sample code on my Email-ID,
    thanks

  3. May 31st, 2010 at 09:07 | #3

    Hi,

    You can if you want, what seems
    To be the problem?

    Cheers,
    Bert

  4. May 31st, 2010 at 17:41 | #4

    @srinivas
    At the moment I don’t have a stacked bar graph available, though the current bar chart code could be adapted to produce a stacked version.

    If I get the time I will try and build one.

    Thanks,
    Bert

  5. srinivas
    June 10th, 2010 at 06:47 | #5

    @Bert
    can u provide some idea to draw a stacked bar chart

    its very urgency for my project.

  6. June 10th, 2010 at 14:46 | #6

    @srinivas
    If you were wanting to have a single bar contained in the graph you can re-write the part of the draw code that renders the bar rects ( see the .mm file the code is down the bottom of the drawRect function ).

    This loops over each of the bar objects and calculates the size of each bar and the renders them to the context using the function CGContextFillRect.

    What you will need to do is loop over all the bars first and work size of each bar part and then render each one. Below is some simple pseudo code that shows how to do the render part.

    float scale = ( the scale factor ); // worked out
    float width = (width of bar );
    float x, y = 0.0f; // start point
    for ( Bar * obj in bars )
    {
    // ————————————————————
    float barHeight = obj.value * scale;
    CGRect barRect = CGRectMake(x, y, width, barHeight);
    x += barHeight;
    // ————————————————————

    // ————————————————————
    // Draw the bar rect
    // ————————————————————
    CGContextSetFillColorWithColor(context,[[obj color] CGColor]);
    CGContextFillRect(context, barRect);
    // ————————————————————
    }

    Hope this helps,
    Bert

  7. srinivas
    June 11th, 2010 at 12:45 | #7

    @Bert

    I will work out with the above coding but bar are rendered. in same values. but were i should change the color and values. i do know. bcoz iam a fresh Iphone developer. Plz help me.

  8. June 11th, 2010 at 13:35 | #8

    @srinivas
    I don’t really know what you are asking for?

    In the above code I store all the specific bar data within the object called “Bar” this contains the
    bar value (or height) it’s colour (as a UIColor object) and a name.

    What’s the value:
    The value is the height of the bar, it is used to work out the render scale for a specific bar in pixels, I use the min max values contained with the graph to work out the scale along with total area I can render the graph into.

    The Name:
    This is used to render the name under the bar.

    Colour the bar:
    When I come to draw the bar I set the color via the function CGContextSetFillColorWithColor. This will block fill the rect with the particular color specified. The context functions also permit you set other colours, best to check the Apple Documentation for a full list.

    I Hope this helps,
    Bert

  9. June 14th, 2010 at 17:49 | #9

    Dear Sir,

    How to reload the graph data?

    I already delete all bars but when add again bars, the image don’t refresh.

    Can you help me?
    Best regards

  10. June 14th, 2010 at 21:04 | #10

    As Abilio has already figured it out the solution.

    As the graph is rendered in a standard view and overloads the drawRect you can use the view function setNeedsDisplayed. This will tell the OS to re-render that view and cause the screen to be recompisited.

    Cheers,
    Bert

  11. srinivas
    June 16th, 2010 at 10:37 | #11

    what type of error this. ans help me to clear this error.

    “.objc_class_name_KECChartStackedColumn”, referenced from:
    literal-pointer@__OBJC@__cls_refs@KECChartStackedColumn in PieChart.o
    “.objc_class_name_KECValueRange”, referenced from:
    literal-pointer@__OBJC@__cls_refs@KECValueRange in PieChart.o
    “.objc_class_name_DTCDefaultCategoryDataset”, referenced from:
    literal-pointer@__OBJC@__cls_refs@DTCDefaultCategoryDatase t in PieChart.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status

    whenever my program executed the above error occurs.

  12. June 17th, 2010 at 11:56 | #12

    @srinivas
    This looks like your linking to an external library or framework that does not exist of the device? Though this is just a guess.

  13. srinivas
    June 19th, 2010 at 09:06 | #13

    can u help me in this . i added already the required framework.
    still this error occurs. how to clear this.

  14. srinivas
    June 19th, 2010 at 12:41 | #14

    in my application is executed in simulator it works.

    but in my iphone device the following error occurs.

    “.objc_class_name_KECChartStackedColumn”, referenced from:
    literal-pointer@__OBJC@__cls_refs@KECChartStackedColumn in PieChart.o
    “.objc_class_name_KECValueRange”, referenced from:
    literal-pointer@__OBJC@__cls_refs@KECValueRange in PieChart.o
    “.objc_class_name_DTCDefaultCategoryDataset”, referenced from:
    literal-pointer@__OBJC@__cls_refs@DTCDefaultCategoryDatase t in PieChart.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status

    any body help me to clear these bug. it’s very urgency.

  15. June 21st, 2010 at 10:19 | #15

    @srinivas
    With out the source code I’m at a bit of a loss, have you been in touch with Keepedge about there library? They may be able to help as the KECChartStackedColumn looks to be from the library provided in the iPhone Charting product.

  16. ashok
    July 10th, 2010 at 15:18 | #16

    Thanks a lot for providing the BarGraph files, I think it would make my life easy but I don’t know how to get started over this.
    I’ve to create a horizontally scrollable bar graph. I would really appreciate if you could provide some tutorial about how to use your BarGraph in general, atleast.
    I’m new to graph creation on iphone or for that matter any platform.

    Thanks again Bert.

  17. ashok
    July 11th, 2010 at 09:59 | #17

    Your code completely suits the need of my app. Thanks man!!
    I added BarGraph view as the subview and did little tweaking in initialization code of bar graph and bar width implementation (at 3 places) in drawRect().

    [self.view addSubview:barGraphView];

    But now I’ve to implement horizontally scrollable feature when there are more bars in the graph than what screen can accommodate? I don’t know how to implement scrollable feature for a view (rather subview in this case).
    Actually the bar graph is the only view for this screen, so I can even add it as the main view but I would prefer it as subview of main view.
    Any help?

    PS: Bert, the BarGraph behavior is not correct (bug) when there is only one bar in bargraph.

  18. July 12th, 2010 at 12:24 | #18

    @ashok
    Sorry need to fix the links, if you pull the code out off the sample project it should at least work :)

    If you want a scrollable bar graph you will need to do a bit of rework, I think your best bet would be to add a scroll view as a sub view in code and then move the bar rendering into that view. Thats just off the top of my head.

    If your having trouble doing this do let me know and I’ll try and throw some sample code together, though I’m currently quite busy finishing off a product.

    Cheers.

  19. ashok
    July 12th, 2010 at 20:22 | #19

    @Bert
    Thanks for the tip. I also realized similar solution for scroll thing. But, I wonder was wondering how to make leftmost vertical grid and vertical axis static/fixed when graph is scrolled horizontally.

    Thanks.

    PS: Avoid my last comment wherein I pointed out the bug for single bar in bargraph. Its actually defined behavior I realized later.

  20. srinivas
    July 15th, 2010 at 12:28 | #20
  21. srinivas
    July 15th, 2010 at 12:29 | #21

    srinivas :
    @ashok

    hello I have issue for merging line and bar can u help in this

  1. No trackbacks yet.