Question

I want to set a larger background for my navigation bar when the screen is switched to landscape mode. So this is what I did in my view controller:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    UIDeviceOrientation deviceOrientation = toInterfaceOrientation;

    if([[UINavigationBar class] respondsToSelector:@selector(appearance)]) {
        [self.navigationController.navigationBar setBackgroundImage: [UIImageHelper createTopBar: deviceOrientation] forBarMetrics: UIBarMetricsDefault];
    }
    else
        [self.navigationController.navigationBar setBackgroundColor: [UIColor colorWithPatternImage: [UIImageHelper createTopBar: [[UIDevice currentDevice] orientation]]]];
}

And this is the createTopBar method:

+ (UIImage *)createTopBar: (UIDeviceOrientation) orientation {
    // Create a new image context
    CGSize size;
    if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight){
        if ([UIDevice isiPhone5]) {
            size = CGSizeMake(568, 34);
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(568, 34), NO, 0.0);
        }
        else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
            size = CGSizeMake(1024, 44);
            UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
        }
        else {
            size = CGSizeMake(480, 34);
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(480, 34), NO, 0.0);
        }
    }
    else{
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
            size = CGSizeMake(768, 44);
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(768, 44), NO, 0.0);
        }
        else if ([UIDevice isiPhone5]) {
            size = CGSizeMake(320, 44);
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(320, 44), NO, 0.0);
        }
        else {
            size = CGSizeMake(320, 44);
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(320, 44), NO, 0.0);
        }
    }
    UIImage * image = [UIImage imageNamed: @"top_bar_without_title"];

    [image drawInRect:CGRectMake(0, 0, size.width, size.height+4)];
    UIImage * destImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return destImage;
}

The result turns out fine in portrait mode:

enter image description here

This also works great in landscape mode in iOS 6:

enter image description here

But this is how it turns out in iOS 7, landscape mode:

enter image description here

You can see the status bar overlaps the navigation bar, and there's some extra space in the bottom of the navigation bar. (On a side note, I have edited the info.plist file to fix the overlapping status bar issue. This only happens when I try to set new background image for the nav bar.) Do you have any suggestion for this problem? If you do, please let me know and thank you.

Was it helpful?

Solution

So thanks to @eagle.dan.1349's answer, I've come up with an idea: I extend the height of navigation bar background to include the height of the status bar, and then start drawing the background image from lower to leave the space for the status bar:

+ (UIImage *)createTopBar: (UIDeviceOrientation) orientation {
    // Create a new image context
    CGSize size;
    if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight){
        if ([UIDevice isiPhone5]) {
            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7){
                size = CGSizeMake(568, 34);
                UIGraphicsBeginImageContextWithOptions(CGSizeMake(568, 54), NO, 0.0);
            }
            else {
                size = CGSizeMake(568, 34);
                UIGraphicsBeginImageContextWithOptions(CGSizeMake(568, 34), NO, 0.0);
            }

        }
        else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
            size = CGSizeMake(1024, 44);
            UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
        }
        else {
            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7){
                size = CGSizeMake(480, 34);
                UIGraphicsBeginImageContextWithOptions(CGSizeMake(480, 54), NO, 0.0);
            }
            else {
                size = CGSizeMake(480, 34);
                UIGraphicsBeginImageContextWithOptions(CGSizeMake(480, 34), NO, 0.0);
            }

        }
    }
    else{
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
            size = CGSizeMake(768, 44);
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(768, 44), NO, 0.0);
        }
        else if ([UIDevice isiPhone5]) {
            size = CGSizeMake(320, 44);
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(320, 44), NO, 0.0);

        }
        else {
            size = CGSizeMake(320, 44);
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(320, 44), NO, 0.0);

        }
    }
    UIImage * image = [UIImage imageNamed: @"top_bar_without_title"];

    if ((orientation == UIInterfaceOrientationLandscapeLeft ||
         orientation == UIInterfaceOrientationLandscapeRight) &&
        [[[UIDevice currentDevice] systemVersion] floatValue] >= 7){

        [[UIColor blackColor] set];
        UIRectFill(CGRectMake(0, 0, size.width, 40));
        [image drawInRect:CGRectMake(0, 20, size.width, size.height+4)];
    }
    else {
        [image drawInRect:CGRectMake(0, 0, size.width, size.height+4)];
    }
    UIImage * destImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return destImage;
}

And voila, it works like a charm! Really hope this could be somehow helpful for someone who's trying to hold on the iOS 6's status bar style like me.

OTHER TIPS

iOS 7 have quite a lot of undocumented behavior in terms of system controls and appearance. I suggest you 'give up' fighting the status bar and adjust your image to fit well under it. You can try just adding 20px of black color at the top of the image.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top