iOS 7 status bar back to iOS 6 default style in iPhone app?
Asked Answered
C

25

294

In iOS 7 the UIStatusBar has been designed in a way that it merges with the view like this:

GUI designed by Tina Tavčar (GUI designed by Tina Tavčar)

  • It is cool, but it will somewhat mess up your view when you have something at the top part of your view, and it becomes overlapped with the status bar.

  • Is there a simple solution (such as setting a property in info.plist) that can change the way it works [not overlapping] back to how it is in iOS6?

  • I know a more straightforward solution is to have self.view.center.x + 20 points for every single view controller, but changing them will screw other dimensions up (having a different self.view.center.x can cause problem to custom segues, etc.) and suddenly it turns into a tedious job that is best to be avoided.

  • I'll really be glad if someone can provide me an one-liner solution for this.

P.S. I know I can hide the status bar by doing things like having

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];

In didFinishLaunchingWithOptions method, but that's a workaround, a shortcut avoiding the problem, so I don't consider that a real solution.

Creath answered 18/8, 2013 at 1:29 Comment(14)
Sadly black status bars were deprecated in ios 7Bastardy
I gonna agree with @GangstaGraham. Those colors are just beautiful! To answer your question, I'm afraid you can't. The reason the status bar is designed like that now is because translucency is the new iOS thing and it is designed to give "depth" to an application by saying it's on top of something, so there is something underneath.Vardar
Have you tried setting preferredStatusBarStyle to UIStatusBarDefault? Checkout iOS 7 UIViewController DocumentationLactoprotein
Having UIStatusBarDefault for the status bar only makes its content black in color. It is not going to make the way it functions back to how it is in iOS6.Jarboe
Any luck with this? I love iOS7 but this thing is driving me crazy!Faultless
Please check if the Apple iOS 7 Transition Guide (developer.apple.com/library/prerelease/ios/documentation/…), specifically the "Updating the UI" section, can help.Directed
I made a snippet, gist 6554189, to avoid the new "status bar overlap feature". It uses autolayout and the newly introduced top layout guide. It works only with autolayout. I didn't test inside the container view controllers, but it could be a good starting point.Bailsman
Archy Hold, How did you get the corder / shadow effect on your view ? I tried to have the same effet since iOS7 is available for developers, and my way to do is is less sexier than yours!! :)Quantize
I post answer there #18917877 Now question frozen.Brenneman
Just curious, what is the name of your app? it has a very nice user interface.Sheepshearing
This link has interesting info on this issue: doubleencore.com/2013/09/…Sharla
Use this answer too https://mcmap.net/q/66623/-status-bar-and-navigation-bar-issue-in-ios7Pettigrew
How did you manage to get the status bar clear? I get a black one on ios6 app migrated to ios7 and added status bar via:if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { [application setStatusBarStyle:UIStatusBarStyleLightContent]; self.window.clipsToBounds =YES; self.window.frame = CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height); self.window.bounds = CGRectMake(0,0, self.window.frame.size.width, self.window.frame.size.height); }Nonpros
If you want to forget what is new on iOS 7 and use iOS 6 and earlier style, take a look to this answerAbduce
T
448

This is cross-posted from a blog post I wrote, but here is the full rundown on status bars, navigation bars, and container view controllers on iOS 7:

  1. There is no way to preserve the iOS 6 style status bar layout. The status bar will always overlap your application on iOS 7

  2. Do not confuse status bar appearance with status bar layout. The appearance (light or default) does not affect how the status bar is laid out (frame/height/overlap). It is important to note as well that the system status bar no longer has any background color. When the API refers to UIStatusBarStyleLightContent, they mean white text on a clear background. UIStatusBarStyleDefault is black text on a clear background.

  3. Status bar appearance is controlled along one of two mutually-exclusive basis paths: you can either set them programmatically in the traditional manner, or UIKit will update the appearance for you based on some new properties of UIViewController. The latter option is on by default. Check your app’s plist value for “ViewController-Based Status Bar Appearance” to see which one you’re using. If you set this value to YES, every top-level view controller in your app (other than a standard UIKit container view controller) needs to override preferredStatusBarStyle, returning either the default or the light style. If you edit the plist value to NO, then you can manage the status bar appearance using the familiar UIApplication methods.

  4. UINavigationController will alter the height of its UINavigationBar to either 44 points or 64 points, depending on a rather strange and undocumented set of constraints. If the UINavigationController detects that the top of its view’s frame is visually contiguous with its UIWindow’s top, then it draws its navigation bar with a height of 64 points. If its view’s top is not contiguous with the UIWindow’s top (even if off by only one point), then it draws its navigation bar in the “traditional” way with a height of 44 points. This logic is performed by UINavigationController even if it is several children down inside the view controller hierarchy of your application. There is no way to prevent this behavior.

  5. If you supply a custom navigation bar background image that is only 44 points (88 pixels) tall, and the UINavigationController’s view’s bounds matches the UIWindow’s bounds (as discussed in #4), the UINavigationController will draw your image in the frame (0,20,320,44), leaving 20 points of opaque black space above your custom image. This may confuse you into thinking you are a clever developer who bypassed rule #1, but you are mistaken. The navigation bar is still 64 points tall. Embedding a UINavigationController in a slide-to-reveal style view hierarchy makes this abundantly clear.

  6. Beware of the confusingly-named edgesForExtendedLayout property of UIViewController. Adjusting edgesForExtendedLayout does nothing in most cases. The only way UIKit uses this property is if you add a view controller to a UINavigationController, then the UINavigationController uses edgesForExtendedLayout to determine whether or not its child view controller should be visible underneath the navigation bar / status bar area. Setting edgesForExtendedLayout on the UINavigationController itself does nothing to alter whether or not the UINavigationController has a 44 or 64 point high navigation bar area. See #4 for that logic. Similar layout logic applies to the bottom of your view when using a toolbar or UITabBarController.

  7. If all you are trying to do is prevent your custom child view controller from underlapping the navigation bar when inside a UINavigationController, then set edgesForExtendedLayout to UIRectEdgeNone (or at least a mask that excludes UIRectEdgeTop). Set this value as early as possible in the life cycle of your view controller.

  8. UINavigationController and UITabBarController will also try to pad the contentInsets of table views and collection views in its subview hierarchy. It does this in a manner similar to the status bar logic from #4. There is a programmatic way of preventing this, by setting automaticallyAdjustsScrollViewInsets to NO for your table views and collection views (it defaults to YES). This posed some serious problems for Whisper and Riposte, since we use contentInset adjustments to control the layout of table views in response to toolbar and keyboard movements.

  9. To reiterate: there is no way to return to iOS 6 style status bar layout logic. In order to approximate this, you have to move all the view controllers of your app into a container view that is offset by 20 points from the top of the screen, leaving an intentionally black view behind the status bar to simulate the old appearance. This is the method we ended up using in Riposte and Whisper.

  10. Apple is pushing very hard to ensure that you don’t try to do #9. They want us to redesign all our apps to underlap the status bar. There are many cogent arguments, however, for both user experience and technical reasons, why this is not always a good idea. You should do what is best for your users and not simply follow the whimsy of the platform.

Tray answered 17/9, 2013 at 16:49 Comment(15)
Just wanted to add that you can add a constraint to whatever is at the top of your view to be attached to the top layout guide - this will leave a blank space behind the status bar (which you can fill in with whatever color you want) but will also allow the view to automatically adjust to the correct position in iOS 6 as well. That way you don't have to manually adjust the position of your views in code.Caresse
That's a brilliant solution. You've exposed my ignorance on AutoLayout. Better get on that.Tray
This was great. Just one thing to add wrt #6. It seems that if a translucent nav bar is used, view controllers with a base view of UIScrollView or derivatives (UITableView, UIWebView) are managed properly by default - they don't tuck under the nav bar, but when scrolling, their content does go under. The "edgesForExtendedLayout" seems useful when you still want a translucent nav bar but have a non-UIScrollView base view in the view controller. Anyways, thanks again for this - it was very helpfulVelasquez
If you place your object's top space beneath the top layout guide's edge, you can use the constraint control to add a vertical spacing constraint to the nearest neighbor, which will now be the top layout guide. Alternatively you can use ctrl+click from your object to the top layout guide to add a vertical spacing constraint explicitly.Caresse
@Caresse One part I don't understand is that -topLayoutGuide is not available on iOS 6, so does that mean you need to use different Auto Layout constraints on iOS 7 and 6?Tetzel
As near as I can tell XCode knows this and automatically adjusts it for you. In iOS 6 the constraint to the top layout guide automatically becomes a constraint to the top of the view.Caresse
Is there anything bad in just making the size of the UIWindow the app runs in 20pt smaller and moving it the 20pts down?Moritz
Great answer...But I have one doubt 1) UINavigationController altering the height part.Please explain it a bit more. thanksElectroanalysis
If you query the UINavCont's navigation bar for it's height, it will return 44 points. But visually, it is obvious that the navigation bar is being drawn (in window coordinates) from an origin of (0,0) to a bottom right corner of (320,64). You can obtain the actual height used view the topLayoutGuide property of the UIViewController that is the visible view controller of the UINavController. It's only when either a) the status bar is hidden or b) the UINC's view's frame isn't contiguous with the UIScreen's bounds that the nag bar will be drawn at a 44 point height.Tray
@Tray Could you view this questions for me: #20040039 because its slightly different, Im using a UITabBarController and nothing seems to work right. I either have to eliminate the status bar completely or if i add space at the top, it eats up space from my tab bar.Nonpros
It deserves 10 votes just for the clue about custom navigation bar background rendering clues.Kilt
@Tray i haveing issue when my UIImagePicker allow editing that appear and when i choose image then after dismiss my statubar going to change eveything its bg color going black andnavigation in statusbarCorky
#4 made me cry a littleMckinleymckinney
And non-web-devs hate CSS because why?Delila
Just want to point out the the y origin of the content below the status bar isn't always 20 (as referenced in point 5 and 9). It is determined by [[UIApplication sharedApplication] statusBarFrame].size.height as other applications such as the phone app may change the height.Dedrick
C
123

Updates on 19th Sep 2013:

fixed scaling bugs by adding self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);

corrected typos in the NSNotificationCenter statement


Updates on 12th Sep 2013:

corrected UIViewControllerBasedStatusBarAppearance to NO

added a solution for apps with screen rotation

added an approach to change the background color of the status bar.


There is, apparently, no way to revert the iOS7 status bar back to how it works in iOS6.

However, we can always write some codes and turn the status bar into iOS6-like, and this is the shortest way I can come up with:

  1. Set UIViewControllerBasedStatusBarAppearance to NO in info.plist (To opt out of having view controllers adjust the status bar style so that we can set the status bar style by using the UIApplicationstatusBarStyle method.)

  2. In AppDelegate's application:didFinishLaunchingWithOptions, call

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        [application setStatusBarStyle:UIStatusBarStyleLightContent];
        self.window.clipsToBounds =YES;
        self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20);
    
        //Added on 19th Sep 2013
        self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
    }
    return YES;
    


in order to:

  1. Check if it's iOS 7.

  2. Set status bar's content to be white, as opposed to UIStatusBarStyleDefault.

  3. Avoid subviews whose frames extend beyond the visible bounds from showing up (for views animating into the main view from top).

  4. Create the illusion that the status bar takes up space like how it is in iOS 6 by shifting and resizing the app's window frame.


For apps with screen rotation,

use NSNotificationCenter to detect orientation changes by adding

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidChangeStatusBarOrientation:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];

in if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) and create a new method in AppDelegate:

- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification
{
    int a = [[notification.userInfo objectForKey: UIApplicationStatusBarOrientationUserInfoKey] intValue];
    int w = [[UIScreen mainScreen] bounds].size.width;
    int h = [[UIScreen mainScreen] bounds].size.height;
    switch(a){
        case 4:
            self.window.frame =  CGRectMake(0,20,w,h);
            break;
        case 3:
            self.window.frame =  CGRectMake(-20,0,w-20,h+20);
            break;
        case 2:
            self.window.frame =  CGRectMake(0,-20,w,h);
            break;
        case 1:
           self.window.frame =  CGRectMake(20,0,w-20,h+20);
    }
}

So that when orientation changes, it will trigger a switch statement to detect app's screen orientation (Portrait, Upside Down, Landscape Left, or Landscape Right) and change the app's window frame respectively to create the iOS 6 status bar illusion.


To change the background color of your status bar:

Add

 @property (retain, nonatomic) UIWindow *background;

in AppDelegate.h to make background a property in your class and prevent ARC from deallocating it. (You don't have to do it if you are not using ARC.)

After that you just need to create the UIWindow in if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1):

background = [[UIWindow alloc] initWithFrame: CGRectMake(0, 0, self.window.frame.size.width, 20)];
background.backgroundColor =[UIColor redColor];
[background setHidden:NO];

Don't forget to @synthesize background; after @implementation AppDelegate!

Creath answered 22/8, 2013 at 17:38 Comment(38)
Oh, if you want a black status bar, use the UINavigation Bar appearance proxy, [[UINavigationBar appearance] setBackgroundImage:someImage] and then the status bar turns black, I don't know how long this will last though because it seems like a bug, but I just thought I'd let you know anyways in case you were still interested in a black status bar.Mannerism
This breaks on rotation. just a heads upDud
@JesseNaugher I recommend modifying Vertical Spacing Constraint from 0 to 20 programmatically. It will work on rotation.Gottwald
That would work for autolayout. I was actually looking for a non-autolayout solution, and found it using Interface Builder and the iOS 6/7 Deltas new in xcode 5.Dud
@JesseNaugher could you share the work around using the deltas pleaseInitial
I'll update this when I have a bit of time to write out an answer: in iOS 7 deadline hell at the moment.Dud
@Mangesh By showing only black status bar do you mean the contents (such as time) are not showing?Jarboe
@Mangesh If that's the case, just set UIViewControllerBasedStatusBarAppearance to NO instead of YES. I misunderstood the documentation and thought YES would do the job. I've corrected it now.Jarboe
@ArchyHolt Thank you for quick responce, ill check and let you know +1Stridor
@ArchyHolt, it is still black,Stridor
@Stridor That's strange. Are your iOS7 & Xcode the latest version (GM seed)? If your OS7 or Xcode is still the beta version there may be bugs.Jarboe
It is showing status bar content in white color with blackbackgroundStridor
Oh then it works. But you want your status bar's background to be other color? Another UIWindow will need to be created for the background. I'll update my answer for that.Jarboe
@ArchyHolt, Thanks for your valuable response, Ill update you once I am on my mac, Back to you on monday. Thank you very Much...Stridor
Any idea on how we can avoid that the navigation bar expands by 20 pixels? This solution is fine for me but my navigation bar is 20 pixels too high.Violative
@ArchyHolt: Your simple solution works for me except when I present a modal view controller. Once the modal view controller is dismissed, the remaining view is now under the status bar. I have reproduced this in a fresh sample project to ensure there is nothing else funky going on. I am thinking maybe your more advanced solution could be useful here but not sure what notification would come into play. Any ideas?Shoreline
@Shoreline Do you mean presenting the modal view controller above another view controller's views (like [[[[UIApplication sharedApplication] delegate] window] insertSubview:modalVC.view aboveSubview:anotherVC.view];?) Can you provide more details on how and where you present the modal view controller and how you dismiss it? If you've got window.clipsToBounds =YES; in AppDelegate, then nothing in that window should be under the status bar, unless you've got the views in another window you created by yourself. Then you just need to shift and resize that window.Jarboe
@JesseNaugher how did you got the solution when not using the Autolayout. Even my project was developed with Xcode4.2 almost 2 yrs back. How did you fixed this issue ?Alkmaar
@ArchyHolt: I am using presentViewController:animated:completion: and dismissViewControllerAnimated:completion:. I have posted a sample project here: bit.ly/1eUKHA1Shoreline
If I do so, on iOS 7 my view have size like UIScreen bounds size and displace by 20 pixels. My view have all autoresizing bits, so I can't see bottom 20 pixels. Do anybody know normal solutions without any hacks? I test on simulator, not real device.Brenneman
The problem I'm having now is that when the app is launched, the orientation is 0.Tove
Has anyone been able to get this solution to work when using a modal view controller? I built a sample application to verify the issue (bit.ly/1eUKHA1). I have not been able to prevent the view from shifting under the status bar once the modal view has been presented/dismissed.Shoreline
This is not working. It adds black status bar without any information in it & also the bottom of the view is cutoff by 20 points.Enzyme
@Shoreline Don't worry. I've already looked into it and fixed this bug by adding self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height); right after self.window.frame = ... in the if statement.Jarboe
@Violative Did adding self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height); after self.window.frame = ... in the if statement work for you?Jarboe
@WillLarche developer.apple.com/library/ios/documentation/uikit/reference/…Jarboe
The view resets after dismissing a modal view controller. :(Northampton
Unfortunately this is not reliable in iPad too. :(Northampton
I was able to make this work guys! Aside from changing the frame and bounds of the window, I also altered the frame of the root view controller. I placed it in the AppDelegate and in the viewDidAppear of my controller. :DNorthampton
Not working with orientation change.. is there any change in code ?Kenric
This doesn't working when hiding Navigationbar What to do?Phlebotomize
@Northampton : Can you provide me sample code what you are talking? at [email protected] please... I am facing problem after using ImagePicker...Stelly
when I use self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height); still my top is getting cutted... when I use self.window.bounds = CGRectMake(0, 0, self.window.frame.size.width, self.window.frame.size.height); it works (0 instead of 20 at y position).. **but only 10px top part get cut). any idea why?Stelly
@Jesse Naugher Got any solution for Status bar breaks?Peashooter
Rotation on iPad and occasionally on iPhone will et messed up if going into a few layers deep in the nav controller, rotating and then pressing back. The content ends up under the nav bar. Almost as if the frame isn't set correctly. Is there any way to solve this?Uboat
Didn't work for me unless I set _background.windowLevel = UIWindowLevelStatusBar - 1;Krebs
You know an API sucks when you see a name like UIApplicationDidChangeStatusBarOrientationNotificationNoctiluca
Don't use 20 for determining the height of the status bar. Use [[UIApplication sharedApplication] statusBarFrame].size.height. Certain scenarios may increase the size of the status bar, such as when in a phone call.Dedrick
C
41

UPDATE(NEW SOLUTION)

This update is the best solution of iOS 7 navigation bar problem.You can set navigation bar color example: FakeNavBar.backgroundColor = [UIColor redColor];

Note : If you use default Navigation Controller please use old solution.

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    if(NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0)
    {
        UIView *FakeNavBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
        FakeNavBar.backgroundColor = [UIColor whiteColor];

        float navBarHeight = 20.0;
        for (UIView *subView in self.window.subviews) {

            if ([subView isKindOfClass:[UIScrollView class]]) {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height - navBarHeight);
            } else {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height);
            }
        }
        [self.window addSubview:FakeNavBar];
    }

    return YES;

}

OLD SOLUTION - IF you use previous code please ignore following Code and Image

This is old version of iOS 7 navigation bar solution.

I solved the problem with the following code. This is for adding a status bar. didFinishLaunchingWithOptions

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    UIView *addStatusBar = [[UIView alloc] init];
    addStatusBar.frame = CGRectMake(0, 0, 320, 20);
    addStatusBar.backgroundColor = [UIColor colorWithRed:0.973 green:0.973 blue:0.973 alpha:1]; //change this to match your navigation bar
    [self.window.rootViewController.view addSubview:addStatusBar];
}

And for Interface Builder this is for when you open with iOS 6; it is starting at 0 pixels.

Note: iOS 6/7 Deltas only appear if you uncheck "Use Autolayout" for the View Controller in the "File Inspector" (left-most icon) in the details pane.

Enter image description here

Cracow answered 23/9, 2013 at 18:35 Comment(7)
You made my day.Take +1 for the help!Geaghan
Please note: iOS 6/7 Deltas only appear if you uncheck "Use Autolayout" for the View Controller in the "File Inspector" (left-most icon) in the details pane.Mucilaginous
What if my storyboard is uses autolayout feature and still requires to provide delta? How to support both of these?Myrtia
@Myrtia i think You should select your view in the storyboard and see this propertyBarney
Who said iOS 6 style status bar layout cannot be maintained, You can do this by @TacettinÖzbölük way... thanks mate for this awsum solution.Archiplasm
I have to set delta Y to 20 instead of -20 to make it work (View as iOS 6.1 or later, starting at Y=0). And setting this directly at the view controller's view won't have any effect. You have to change each of its subviews (another view inside).Unstopped
nice one! also, just to note apple prefer this now: if (NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_6_1) {}Antisthenes
B
26

SOLUTION :

Set it in your viewcontroller or in rootviewcontroller by overriding the method :

-(BOOL) prefersStatusBarHidden
    {
        return YES;
    }
Blimp answered 18/9, 2013 at 13:38 Comment(4)
Not a bad solution. Completely remove the bar. Might not be ideal for UX all the time but workable.Gender
Simply Awesome. Worked for me Flawlessly.Greaseball
Scenario: Once I switch back to my UIVIew after playing the video fullscreen, a black bar appears at the bottom which is just the size of status bar,although, I was already using a status bar. I removed the status bar altogether and now the issue is fixed.Greaseball
I have only been successful using this methodAcute
S
17

Here another approach for projects that make extensive use of the Storyboard:

GOAL:

Goal of this approach is to recreate the same status bar style in iOS7 as there was in iOS6 (see question title "iOS 7 Status Bar Back to iOS 6 style?").

SUMMARY:

To achieve this we use the Storyboard as much as possible by shifting UI elements that are overlapped by the status bar (under iOS 7) downwards, whilst using deltas to revert the downwards layout change for iOS 6.1 or earlier. The resulting extra space in iOS 7 is then occupied by a UIView with the backgroundColor set to a color of our choosing. The latter can be created in code or using the Storyboard (see ALTERNATIVES below)

ASSUMPTIONS:

To get the desired result when following the steps below, it is assumed that View controller-based status bar appearance is set to NO and that your Status bar style is either set to "Transparent black style (alpha of 0.5)" or "Opaque black style". Both settings can be found/or added under "Info" in your project settings.

STEPS:

  • Add a subview to the UIWindow to serve as your status bar background. To achieve this, add the following to your AppDelegate's application: didFinishLaunchingWithOptions: after makeKeyAndVisible

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        UIView *statusBarBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, yourAppsUIWindow.frame.size.width, 20)];
        statusBarBackgroundView.backgroundColor = [UIColor blackColor];
        [yourAppsUIWindow addSubview:statusBarBackgroundView];
    }
    
  • Since you programmatically added a background for iOS 7 ONLY, you will have to adjust the layout of your UI elements that are overlapped by the status bar accordingly whilst preserving their layout for iOS6. To achieve this, do the following:

    • Ensure that Use Autolayout is unchecked for your Storyboard (this is because otherwise "iOS 6/7 Deltas" is not shown in the Size Inspector). To do this:
      • select your Storyboard file
      • show Utilities
      • select "Show the File Inspector"
      • Under "Interface Builder Document" uncheck "Use Autolayout"
    • Optionally, to help you monitor the layout changes for both iOS 7 AND 6 as you apply them, select the "Assistant Editor", select "Preview" and "iOS 6.1 or earlier": enter image description here enter image description here
    • Now select the UI element you want to adjust so it isn't overlapped by the status bar anymore
    • Select "Show the Size Inspector" in the Utilities column
    • Reposition your UI element along the Y-axis by the same amount as the statusbar bg height: enter image description here
    • And change the iOS6/7 Deltas value for Y by the same NEGATIVE amount as the statusbar bg height (Note the change in the iOS 6 preview if you're using it): enter image description here

ALTERNATIVES:

To add even less code in storyboard-heavy projects and to have the statusbar background autorotate, instead of programmatically adding a background for your statusbar, you could add a colored view to each view controller that sits at the very top of said viewcontroller's main view. You would then change the height delta of this new view to the same negative amount as your view's height (to make it disappear under iOS 6).

The downside of this alternative (although maybe negligible considering the autorotate compatibility) is the fact that this extra view is not immediately visible if you are viewing your Storyboard for iOS 6. You would only know that it's there if you had a look at the "Document Outline" of the Storyboard.

Spicule answered 18/8, 2013 at 1:29 Comment(0)
K
12

If you don't want your view controllers to be overlapped by the status bar (and navigation bars), uncheck the "Extend Edges Under Top Bars" box in Interface Builder in Xcode 5.

Uncheck the Extend Edges Under Top Bars

Kreegar answered 12/9, 2013 at 22:21 Comment(9)
This is only possible if you use a storyboardDukes
It works only with containers vcs such as navigation controller or tabbar controllerBailsman
edgesForExtendedLayout is only used by container view controllers (like UINavigationController) to determine whether it's children's views should be overlapped by the parent's chrome. Setting this property on the root view controller for the UIWindow does nothing. See my answer above: #18295372Tray
How do you do it for a UITabBarController @Andrea? Thanks.Northampton
@Northampton Depend if you do programmatically or with storyboards. Programmatically you just need to set the edgesForExtent property to what you like in the view controller you are showing inside the UITabBarViewController, but to do not have the problem of the status bar you must load a uinavigationcontroller inside the th UITabbarController. Check here. developer.apple.com/library/ios/documentation/UserExperience/…Bailsman
Hi @Andrea, so it will not work if I only have a UITabBarController and not a UINavigationController?Northampton
Depends on what you want to achieve. If your problem is the status bar, but your views are inside only a tabbarcontroller, this isn't the right solution. edgesForExtent works only in standard container view controllers and it just say if the view controller can stay under the tab bar or the navigation bar. Since navbar in iOS7 are sort of an extensions of the status bar, if you avoid navbar you avoid status bar.Bailsman
It works but the color of the tab bar and the tab bar gets darker than normal white. Did this happen to you guys?Jacobsohn
@FrankGorman The tab bar color gets darker because it is partially translucent and this option moves the view out from under the tab bar.Kreegar
O
11

Apple released Technical Q&A QA1797: Preventing the Status Bar from Covering Your Views. It works fine for the iOS 6 and iOS 7 versions.

Ohg answered 25/9, 2013 at 7:58 Comment(3)
Apple is assuming everyone is using auto-layout. Auto-layout was horrible in Xcode 4, and Xcode 5 was only just released, so this is a dubious assumption.Cattleya
But in prospect this is a better solution then resize frame of root window or status bar.Ohg
As far as I can tell, Apple's solution does not work if your rootViewController is a splitViewController.Lantha
E
8

I have viewed many many many many and many tutorials to fix this darn problem. But none of them works! Here is my solution, and it works for me:

if( [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f ) {
    float statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
    for( UIView *v in [self.view subviews] ) {
        CGRect rect = v.frame;
        rect.origin.y += statusBarHeight;
        v.frame = rect;
    }
}

The logic is simple. I shift all children views on the self.view with 20 pixels. That's all. Then, the screenshot will display just like as iOS 6 did. I hate the iOS7 status bar! ~"~

Exeter answered 27/9, 2013 at 7:55 Comment(2)
where should I add this? in app delegate did launch with options?Roanne
When I do this, my status bar turns whiteMacaulay
P
6

A small alternative to Archy Holt's answer, a bit more simple:

a. Set UIViewControllerBasedStatusBarAppearance to NO in info.plist

b. In AppDelegate's application:didFinishLaunchingWithOptions:, call:

if ([[UIDevice currentDevice].systemVersion floatValue] < 7)
{
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
}
else
{
    // handling statusBar (iOS7)
    application.statusBarStyle = UIStatusBarStyleLightContent;
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    self.window.clipsToBounds = YES;

    // handling screen rotations for statusBar (iOS7)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangeStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}

And add the method:

- (void)applicationDidChangeStatusBarOrientationNotification:(NSNotification *)notification
{
    // handling statusBar (iOS7)
    self.window.frame = [UIScreen mainScreen].applicationFrame;
}

You can also consider subclassing UIWindow to handle UIApplicationDidChangeStatusBarOrientationNotification itself.

Peralta answered 18/9, 2013 at 9:21 Comment(2)
do you have problem with presentViewController:animated:completion: ?Briggs
@TùngĐỗ true, so I made an alternative that works better: #18295372Dukes
A
5

I used this in all my view controllers, it's simple. Add this lines in all your viewDidLoad methods:

- (void)viewDidLoad{
    //add this 2 lines:
    if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

    [super viewDidLoad];
}
Abduce answered 22/10, 2013 at 15:40 Comment(1)
Worked like a charm, and dead easy. In ruby motion, before the call to super use: self.edgesForExtendedLayout = UIRectEdgeNone if respondsToSelector("edgesForExtendedLayout")Phonography
T
4

Try this simple method....

Step 1:To change in single viewController

[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque];

Step 2: To change in whole application

info.plist
      ----> Status Bar Style
                  --->UIStatusBarStyle to UIStatusBarStyleBlackOpaque

Step 3: Also add this in each viewWillAppear to adjust statusbar height for iOS7

    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 7) {
        CGRect frame = [UIScreen mainScreen].bounds;
        frame.origin.y+=20.0;
        frame.size.height-= 20.0;
        self.view.frame = frame;
        [self.view layoutIfNeeded];
    }
Teddman answered 15/4, 2014 at 9:4 Comment(0)
F
3

There is an option in the Interface Builder which calls the iOS 6/7 Delta property which aim to solve the offset problem.

Take a look at it in Stack Overflow question Interface Builder: What are the UIView's Layout iOS 6/7 Deltas for?.

Fane answered 16/9, 2013 at 8:4 Comment(0)
R
3

I have achieved status bar like iOS 6 in iOS 7.

Set UIViewControllerBasedStatusBarAppearance to NO in info.plist

Pase this code in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    [application setStatusBarStyle:UIStatusBarStyleLightContent];
    self.window.clipsToBounds =YES;
    self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height);

    //Added on 19th Sep 2013
    NSLog(@"%f",self.window.frame.size.height);
    self.window.bounds = CGRectMake(0,0, self.window.frame.size.width, self.window.frame.size.height);
}

It may push down all your views by 20 pixels.To over come that use following code in -(void)viewDidAppear:(BOOL)animated method

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    CGRect frame=self.view.frame;
    if (frame.size.height==[[NSUserDefaults standardUserDefaults] floatForKey:@"windowHeight"])
    {
        frame.size.height-=20;
    }
    self.view.frame=frame;
}

You have to set windowHeight Userdefaults value after window allocation in didFinishLauncing Method like

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[[NSUserDefaults standardUserDefaults] setFloat:self.window.frame.size.height forKey:@"windowHeight"];
Ribwort answered 27/9, 2013 at 7:5 Comment(8)
A better approach is to make your UINavigationBar's height equal to 64 instead of 44. Then your bar will extend all the way to the top like in Apple's apps.Simitar
@AaronBrager But my requirement was to show iOS 6 style status bar.Ribwort
Can you please add the solution for Landscape Orientation iOS 7?. I am doing the same thing. but it is not working in iOS 7 Landscape.Peashooter
@DesertRose THX! This works for me but it cuts off the uitabbar at the bottom. I have a tab bar controller based app with 3 views, 2 of which are tableviewcontrollers.Nonpros
@Nonpros I have said it in my answer that it may push down your views.Please use that code too for make it look normal.Ribwort
I did use the code and it is still cut off. I added the appDelegate code that starts the window frame at 20 and resets the window.bounds for anything greater than or equal to 7 and uses the user default. Then if >=7 code in the viewWillAppear I added the other code as well. The status bar appears fine up at top but the tab bar of the tabbarcontroller is still cut offNonpros
UNTIL I rotate the device (my iOS 7 device is an iPad), this fixes it perfectly. But once I rotate, the black bar remains exactly where it is and the "view" (sorry if that's the wrong technical term, I'm a PhoneGap/web guy) maintains its shrunken height -- except it's no longer the height, it's the width. This solution doesn't support rotation but it's the best fix I've seen - how can it be improved to watch for device rotations? Thanks!Brusquerie
This answer apparently works great for many but for others, especially those using PhoneGap, the solution seems to be using code from this answer: https://mcmap.net/q/66625/-ios-7-status-bar-overlapping-uiBrusquerie
A
2

If you're using Interface builder, try this:

In your xib file:

1) Select the main view, set the background color to black (or whatever color you want the status bar to be

2) Make sure the background is a self contained subview positioned as a top level child of the controller's view.
Move your background to become a direct child of the controller's view. Check the autosizing panel to be sure that you've locked all frame edges, activated both flexibility axes, and if this is a UIImageView, set the content mode to Scale to fill. Programmatically this translates to contentMode set to UIViewContentModeScaleToFill and has its auto resizing mask set to (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight).

3) Now move everything that is locked to the top - down by 20 pts and set a iOS 6/7 delta Y to -20.
All top level children that are locked to the top frame in the autosizing panel need to be moved down by 20pts and have their iOS 6/7 delta Y set to -20. (Cmd select all of those, and click down arrow 20 times - is there a better way anyone?)

4) Adjust the iOS 6/7 delta height of all of the above items that had a flexible height. Any of the items that were locked to the frame top and bottom and had flexible height enabled in the autosizing panel must also have their iOS 6/7 delta height set to 20. That includes the background view mentioned above. This may seem anti-intuitive, but due to the order in which these are applied, it is necessary. The frame height is set first (based on device), then the deltas are applied, and finally the autosizing masks are applied based upon the offset positions of all of the child frames - think it through for a bit, it will make sense.

5) Finally, items that were locked to the bottom frame but not the top frame need no deltas at all.

That will give you the identical status bar in iOS7 and iOS6.

On the other hand, if you want iOS7 styling while maintaining iOS6 compatibility, then set the delta Y / delta height values to 0 for the background view.

To see more iOS7 migration info read the full post: http://uncompiled.blogspot.com/2013/09/legacy-compatible-offsets-in-ios7.html

Axon answered 23/9, 2013 at 0:30 Comment(1)
No deltas when using auto layoutDivest
H
2

My solution was to add a UIView with height of 20 points on top of the window when on iOS 7. Then I created a method in my AppDelegate class to show/hide the "solid" status bar background. In application:didFinishLaunchingWithOptions::

// ...

// Add a status bar background
self.statusBarBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.bounds.size.width, 20.0f)];
self.statusBarBackground.backgroundColor = [UIColor blackColor];
self.statusBarBackground.alpha = 0.0;
self.statusBarBackground.userInteractionEnabled = NO;
self.statusBarBackground.layer.zPosition = 999; // Position its layer over all other views
[self.window addSubview:self.statusBarBackground];

// ...
return YES;

Then I created a method to fade in/out the black status bar background:

- (void) showSolidStatusBar:(BOOL) solidStatusBar
{
    [UIView animateWithDuration:0.3f animations:^{
        if(solidStatusBar)
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
            self.statusBarBackground.alpha = 1.0f;
        }
        else
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
            self.statusBarBackground.alpha = 0.0f;
        }
    }];
}

All I have to do now is call is [appDelegate showSolidStatusBar:YES] when needed.

Hyaloid answered 27/9, 2013 at 21:12 Comment(0)
J
2

This may be a overwhelming problem if you use Auto layout because you can not directly manipulate frames anymore. There is a simple solution without too much work.

I ended up writing an utility method in an Utility Class and called it from all the view controllers's viewDidLayoutSubviews Method.

+ (void)addStatusBarIfiOS7:(UIViewController *)vc
    {
        if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
            CGRect viewFrame = vc.view.frame;
            if(viewFrame.origin.y == 20) {
                //If the view's y origin is already 20 then don't move it down.
                return;
            }
            viewFrame.origin.y+=20.0;
            viewFrame.size.height-= 20.0;
            vc.view.frame = viewFrame;
            [vc.view layoutIfNeeded];
        }
    }

Override your viewDidLayoutSubviews method in the view controller, where you want status bar. It will get you through the burden of Autolayout.

- (void)viewDidLayoutSubviews
{
    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    [super viewDidLayoutSubviews];
    [MyUtilityClass addStatusBarIfiOS7:self];
}
Jackknife answered 28/3, 2014 at 17:18 Comment(0)
C
1

The easiest way to do so is installing an older SDK to your newest Xcode.

How to install older SDK to the newest Xcode?

  1. U can get the iOS 6.1 SDK from http://www.4shared.com/zip/NlPgsxz6/iPhoneOS61sdk.html or downloading an older Xcode and geting the SDK from its contents

  2. Unzip and paste this folder to /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs

  3. Restart the xcode.

  4. U can now select an older SDK on your project's build settings

Hope it helps you. It worked for me =)

Cohbath answered 3/10, 2013 at 19:6 Comment(5)
worked for me. thanks @Cohbath but still searching for a workaround for my phonegap (uiwebview) app to support iOS7's transparent status bar for future update of my app. thanks again. ;)Baldpate
@marcellosaloum, are you sure the app will be accepted by Apple? They said the apps compiled with XCode 4 would no longer be accepted...that as a matter of fact means iOS 6 SDK.Diversion
My app was indeed accepted because Xcode5 can compile older iOS SDKs. I am not sure if AppStore will reject Xcode4 built apps but (Xcode4 != iOS 6 SDK) as you said.Cohbath
Was that after the 1st of February? In that day Apple made that mandatory.Diversion
No, last touched that code last year, folk. Didn't know Apple had made that mandatory (not happy to know though). Would you please post here the link that says that? CheersCohbath
P
1

As using presentViewController:animated:completion: messed-up the window.rootViewController.view, I had to find a different approach to this issue. I finally got it to work with modals and rotations by subclassing the UIView of my rootViewController.

.h

@interface RootView : UIView

@end

.m

@implementation RootView

-(void)setFrame:(CGRect)frame
{
    if (self.superview && self.superview != self.window)
    {
        frame = self.superview.bounds;
        frame.origin.y += 20.f;
        frame.size.height -= 20.f;
    }
    else
    {
        frame = [UIScreen mainScreen].applicationFrame;
    }

    [super setFrame:frame];
}

- (void)layoutSubviews
{
    self.frame = self.frame;

    [super layoutSubviews];
}

@end

You now have a strong workaround for iOS7 animations.

Peralta answered 8/10, 2013 at 16:47 Comment(0)
A
1

I am late for this Answer, but i just want to share what i did, which is basically the easiest solution

First of all-> Go to your info.plist File and add Status Bar Style->Transparent Black Style(Alpha of 0.5)

Now ,here it Goes:-

Add this code in your AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
     //Whatever your code goes here
  if(kDeviceiPad){

     //adding status bar for IOS7 ipad
         if (IS_IOS7) {
              UIView *addStatusBar = [[UIView alloc] init];
              addStatusBar.frame = CGRectMake(0, 0, 1024, 20);
              addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //change this to match your navigation bar
              [self.window.rootViewController.view addSubview:addStatusBar];
                    }
                }
    else{

         //adding status bar for IOS7 iphone
        if (IS_IOS7) {
            UIView *addStatusBar = [[UIView alloc] init];
            addStatusBar.frame = CGRectMake(0, 0, 320, 20);
            addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //You can give your own color pattern
            [self.window.rootViewController.view addSubview:addStatusBar];
        }

    return YES;
   }
Archiplasm answered 26/2, 2014 at 6:39 Comment(0)
A
0

You can hide the status bar all together. So your app will be full-screen. I think that's the best you will get.

UIStatusBarStyleNone or set in the target settings.

Alundum answered 22/8, 2013 at 16:29 Comment(1)
where to specify UIStatusbarstylenoneHelenehelenka
S
0

My very simple solution (assuming you have only vertical orientation supported) is to redefine application window bounds for iOS versions below 7, in App delegate didFinishLaunchingWithOptions method:

CGRect screenBounds = [[UIScreen mainScreen] bounds];
if ([HMService getIOSVersion] < 7) {
    // handling statusBar (iOS6) by leaving top 20px for statusbar.
    screenBounds.origin.y = 20;
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
else {
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
Si answered 19/9, 2013 at 14:55 Comment(1)
Your code just shifts the 'y' from 0 to 20 but does not adjust height accordingly so you should add screenBounds.size.height -= 20; just after screenBounds.origin.y = 20;Rhaetia
O
0

Steps For Hide the status bar in iOS 7:

1.Go to your application info.plist file.

2.And Set, View controller-based status bar appearance : Boolean NO

Hope i solved the status bar issue.....

Organon answered 30/1, 2014 at 11:43 Comment(0)
J
0

In order to continue working with setStatusBarHidden: I use this category:

@interface UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden;

@end

@implementation UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden{
    if (!IOS7) {
        [self setStatusBarHidden:statusBarHidden];
        return;
     }

    if ([self isStatusBarHidden] == statusBarHidden) {
        return;
    }

    [self setStatusBarHidden:statusBarHidden];
    [self keyWindow].clipsToBounds = YES;
    CGFloat offset = statusBarHidden ? 0 : 20;
    [self keyWindow].frame =  CGRectMake(0,offset,[self keyWindow].frame.size.width,[self keyWindow].frame.size.height-offset);
    [self keyWindow].bounds = CGRectMake(0, offset, [self keyWindow].frame.size.width,[self keyWindow].frame.size.height);
}

@end
Joleen answered 8/2, 2014 at 21:25 Comment(0)
I
0

I found here is the best alternatives and solution for this navigation bar issue in iOS7!!

http://www.appcoda.com/customize-navigation-status-bar-ios-7/

I hope it will clear our all queries and worries.

Ingressive answered 26/3, 2014 at 6:30 Comment(0)
M
0

This might be too late to share, but I have something to contribute which might help someone, I was trying to sub-class the UINavigationBar and wanted to make it look like ios 6 with black status bar and status bar text in white.

Here is what I found working for that

        self.navigationController?.navigationBar.clipsToBounds = true
        self.navigationController?.navigationBar.translucent = false
        self.navigationController?.navigationBar.barStyle = .Black
        self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()

It made my status bar background black, status bar text white and navigation bar's color white.

iOS 9.3, XCode 7.3.1

Mellissamellitz answered 31/5, 2016 at 11:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.