lostInTransit
lostInTransit

Reputation: 71047

Custom background for UINavigationBar in landscape mode

I am adding a custom background for my UINavigationBar. It works fine as long as the phone is in portrait mode. As soon as I switch to landscape mode, half the bar appears blue (the default navbar color) and half of it has my image

How can I stretch the image for landscape mode and make it small again for portrait mode?

Thanks

Solution
Incase anyone is looking for an answer to how to add an image to navigation bar - here goes

UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 480.0, 44.0)];
[imgView setImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"navbar_landscape" ofType:@"png"]]];
[navigationController.navigationBar addSubview:imgView];
[imgView release];

Upvotes: 7

Views: 8900

Answers (6)

Ahmet Ardal
Ahmet Ardal

Reputation: 1172

You can change the image for both portrait and landscape orientations by supplying different images for different orientations by checking the frame size of that UINavigation bar instance:

- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
    if ([self isMemberOfClass:[UINavigationBar class]] == NO) {
        return;
    }

    UIImage *image = (self.frame.size.width > 320) ?
                        [UINavigationBar bgImageLandscape] : [UINavigationBar bgImagePortrait];
    CGContextClip(context);
    CGContextTranslateCTM(context, 0, image.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(context, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), image.CGImage);
}

And this complete demo Xcode project on customizing the appearance of UINavigationBar might be helpful. It also includes @2x versions of background images to support retina displays on iPhone 4 devices.

Upvotes: 1

Nuthatch
Nuthatch

Reputation: 3597

Try the simpler method of [UIImage imageNamed:@"navbar_landscape.png"] since a UI element is exactly what imageNamed: is intended for, as ljonesATL shows.

Upvotes: 0

ljonesATL
ljonesATL

Reputation: 191

After a bit of research and trail and error, I found a work around, that will not replace the navbar when you enter the movie playback mode. Hopeefully this does not cause problems with app approval, but based on this post, I think it should be fine:

http://developer.apple.com/iphone/library/qa/qa2009/qa1637.html

@implementation UINavigationBar (UINavigationBarCategory)

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    if([self isMemberOfClass: [UINavigationBar class]]){
        UIImage *image = [UIImage imageNamed:@"navBarBackground.png"];
        CGContextClip(ctx);
        CGContextTranslateCTM(ctx, 0, image.size.height);
        CGContextScaleCTM(ctx, 1.0, -1.0);
        CGContextDrawImage(ctx, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), image.CGImage);
    }else{
        [super drawLayer:layer inContext:ctx];
    }
}

@end

Upvotes: 6

Ivan Karpan
Ivan Karpan

Reputation: 1554

In both screen orientation modes it's much better to use

[navigationController.navigationBar insertSubview:imgView atIndex:0];

This puts image view under all other views and all the default navigation bar elements (title, standard buttons) work OK.

Upvotes: 6

lostInTransit
lostInTransit

Reputation: 71047

The solution Ben gave did solve the problem but it stretches the image in landscape mode. I ended up creating two images- one for landscape and other for the portrait mode. I then added code in shouldAutoRotate to change the navbar image based on the orientation

Upvotes: 1

Ben Gottlieb
Ben Gottlieb

Reputation: 85542

You probably need to set the autoresizingMask of your background image view; try using UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight

Upvotes: 3

Related Questions