Cocoa in the Shell

[iOS] Custom status bar

Nov 29, 2010

In this article I will show you how you can create your own status bar to display informations like you may have seen in Reeder or Pulse apps. The code doesn’t use any private API so you won’t have any trouble with App Store validation.

To illustrate how to create our own custom status bar, I will create one with a UIActivityIndicatorView and a UILabel to display some text.

The first thing we need to do is to create a subclass of UIWindow and override initWithFrame method.

@interface CustomStatusBar : UIWindow
{
@private
    UILabel* _statusLabel; // Text label to display informations
    UIActivityIndicatorView* _indicator; // The indicator
}
-(void)showWithStatusMessage:(NSString*)msg;
-(void)hide;

@end

#import "CustomStatusBar.h"

@implementation CustomStatusBar

-(id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame]))
    {
        // Place the window on the correct level & position
        self.windowLevel = UIWindowLevelStatusBar + 1.0f;
        self.frame = [UIApplication sharedApplication].statusBarFrame;
        // Create an image view with an image to make it look like the standard grey status bar
        UIImageView* backgroundImageView = [[UIImageView alloc] initWithFrame:self.frame];
        backgroundImageView.image = [[UIImage imageNamed:@"statusbar_background.png"] stretchableImageWithLeftCapWidth:2 topCapHeight:0];
        [self addSubview:backgroundImageView];
        [backgroundImageView release];

        _indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        _indicator.frame = (CGRect){.origin.x = 2.0f, .origin.y = 3.0f, .size.width = self.frame.size.height - 6, .size.height = self.frame.size.height - 6};
        _indicator.hidesWhenStopped = YES;
        [self addSubview:_indicator];

        _statusLabel = [[UILabel alloc] initWithFrame:(CGRect){.origin.x = self.frame.size.height, .origin.y = 0.0f, .size.width = 200.0f, .size.height = self.frame.size.height}];
        _statusLabel.backgroundColor = [UIColor clearColor];
        _statusLabel.textColor = [UIColor blackColor];
        _statusLabel.font = [UIFont boldSystemFontOfSize:10.0f];
        [self addSubview:_statusLabel];
    }
    return self;
}

-(void)dealloc
{
    [_statusLabel release];
    [_indicator release];
    [super dealloc];
}

Now we need two methods to display and hide the status bar

-(void)showWithStatusMessage:(NSString*)msg
{
    if (!msg) return;
    _statusLabel.text = msg;
    [_indicator startAnimating];
    self.hidden = NO;
}

-(void)hide
{
    [_indicator stopAnimating];
    self.hidden = YES;
}

That’s all, we are done with our custom status bar class, now we can use it somewhere in our code.

For example let’s say I’m downloading some data and I want to show this within a custom status bar instead of just animating the traditional UIApplication’s networkActivityIndicator.

In my controller class I declare a CustomStatusBar ivar and instantiate it.

-(void)viewDidLoad
{
    [super viewDidLoad];

    _customStatusBar = [[CustomStatusBar alloc] initWithFrame:CGRectZero]; // Don't forget to release
}

Now when you want to display it you just have to call the showWithStatusMessage: method and this will hide the original status bar with our custom one.

You can download the code here.

Tags: ,