Search code examples
iosuinavigationcontrollerstatusbarios11uistatusbar

Status bar background disappears while hiding on iOS 11


As of iOS 11, the status bar in my app is misbehaving when I dismiss it. The background of the status bar turns clear while the status bar is being dismissed. It didn't do this in iOS 10.

status bar bug

I've recreated the issue in a very simple application, which I've uploaded on Github: TestStatusBarBug. Here is all of the relevant code:

AppDelegate.m

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[UINavigationBar appearance] setBarTintColor:[UIColor grayColor]];
    return YES;
}

@end

ViewController.m

#import "ViewController.h"

@interface ViewController () {
    BOOL _statusBarHidden;
}

@end

@implementation ViewController

-(BOOL)prefersStatusBarHidden
{
    return _statusBarHidden;
}

-(UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
    return UIStatusBarAnimationSlide;
}

- (IBAction)toggleStatusBar {
    _statusBarHidden = !_statusBarHidden;

    [UIView animateWithDuration:0.35 animations:^{
        [self setNeedsStatusBarAppearanceUpdate];
    }];
}

@end

Has anyone else experienced this issue? Is there a fix or a workaround?


Solution

  • I looked at the project and by changing your view colors, I was able to determine that the white color you're seeing is coming from the view with the button in it (it's the background color).

    When you're hiding the status bar, the navigation bar is still at its old location (20 pixels too low now), so the white background of the view shows through. Then the navigation bar lays out/moves up and the white goes away.

    Why this behavior has changed in iOS 11, I can't say, but it's not unusual for mechanics behind view operations to change during a major iOS update. Fortunately, there's an easy solution.

    When you do the animation for the status bar visibility change, also force the navigation bar to layout. That will cause it to be positioned correctly and the animation will look correct.

    Just add these last two lines for laying out the navigation bar to your toggle code.

    - (IBAction)toggleStatusBar {
        _statusBarHidden = !_statusBarHidden;
    
        [UIView animateWithDuration:0.35 animations:^{
            [self setNeedsStatusBarAppearanceUpdate];
            [self.navigationController.navigationBar setNeedsLayout];
            [self.navigationController.navigationBar layoutIfNeeded];
        }];
    }