58

I am migrating my application to iOS 7. For handing the status bar issue I have added this code

if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f)
{
    CGRect frame = self.navigationController.view.frame;
    if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
    {
        frame.origin.y = 20;
    }
    else
    {
        frame.origin.x = 20;
    }
    [self.navigationController.view setFrame:frame];
}

This is working fine in normal case. If I am changing orientation (app supports only landscape orientation) or presenting any view controller and dismissing model view controller my view controller alignment changed. The status bar again overlaps my view controller. This piece of code is not working at all. Please guide me to fix this status bar issue.

Case 2: This is how I am presenting my view controller

ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
    
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    reader.supportedOrientationsMask = ZBarOrientationMaskLandscape;
else
    reader.supportedOrientationsMask = ZBarOrientationMaskPortrait;
    
    [self presentModalViewController:reader animated:YES];

Ref:

enter image description here

starball
  • 20,030
  • 7
  • 43
  • 238
Ganapathy
  • 4,594
  • 5
  • 23
  • 41
  • As i mentioned, If orientation change the status bar over lap issue occur, not even presentmodelviewcontroller case alone. – Ganapathy Sep 24 '13 at 12:29
  • 1
    Here is a straight forward answer to this question: http://stackoverflow.com/questions/18775874/ios-7-status-bar-overlaps-the-view – aryaxt Oct 02 '13 at 15:35

11 Answers11

133

Fix for status bar issue in IOS 7

Finally I fixed the status bar over lap issue using the delta value property in xcode5. First I have increased origin - y 20pxl to all the controller used in the Xib (it seams to be working fine only in IOS 7), after that I set the delta value for all the view controller origin -y to -20 it works fine in both iOS 6 and iOS 7.

Steps to do that.

Xcode 5 provide preview option to view the appearance of the xib in different view based on the OS version.

Choose preview option from assistant editor

Click assistant editor

enter image description here

and choose preview option to preview selected view controller in different version.

enter image description here

view controller view preview option.

enter image description here

in preview you can find the toggle option to preview view in different version. In preview u can feel the status bar issue clearly if its not fixed properly by toggle the version.

Three steps to fix the status bar issue: step 1: Make sure the view target us 7.0 and later in File inspector.

enter image description here

Step 2 : Increase the origin - y with 20 pixel (exactly the size of the status bar) for all the controls added in the view controller.

Step 3 : Set the delta value of origin y to -20 for all the controls then only it will adjust automatically based on the version. Use preview now and feel the differ that the controls automatically adjust because of the delta value.

enter image description here

Once the status bar issue fixed, issue while presenting the model view (ZbarSDk controller) is also fixed automatically.

Preview screen :

enter image description here

halfer
  • 19,824
  • 17
  • 99
  • 186
Ganapathy
  • 4,594
  • 5
  • 23
  • 41
  • 10
    Leave a comment if you are not satisfy( who gave me down vote -1) with this answer. So that i can improve my answer. – Ganapathy Sep 27 '13 at 03:58
  • What to do it programmatically, if I don't define .xib? P.S. I'm an upvoter :D (to @Ganapathy) – George Oct 01 '13 at 07:53
  • 1
    if you added controls programmatically, you need to increase the origin y to 20 for all the added controls(Which are added programmatically)if the device version is about 7.0.. – Ganapathy Oct 01 '13 at 08:38
  • 2
    When I go with your steps the I am unable to set my view potion +20 as you mention in #step2 as it is disabled. How do i make editable? – ASHISHT Oct 02 '13 at 07:16
  • I think you are trying to change the origin for yours root view. check once. Check the sub view origin values. – Ganapathy Oct 02 '13 at 13:20
  • @Ganapathy: If we have created controls programmatically and if we increase y offset by 20, it will work fine for iOS 7 but what should we do to make it compatible to iOS 6? – Mano Oct 11 '13 at 04:40
  • Increase the y offset if the version in above ios 7. if([[[UIDevice CurrentDevice] SystemVersion] floatValue] >= 7.0){ Increase the offset value for the control that you have created programmatically} – Ganapathy Oct 11 '13 at 05:54
  • This was what finally clued me in on how to fix this issue, thanks so much – jakev Oct 14 '13 at 22:52
  • Hi @Ganapathy I want to know where's the preview option? – Vigor Nov 01 '13 at 06:43
  • You have to choose it from assistant editor(Middle button in right side inspector bundle). Please see my first point. – Ganapathy Nov 02 '13 at 02:31
  • To @Ganapathy, How can we make sure **Use Autolayout** is unchecked when creating views programmatically instead of using nib/IB? – George Nov 04 '13 at 11:00
  • To @Ganapathy, Finally, this really solved my problem: *"If you added controls programmatically, you need to increase the origin y to 20 for all the added controls (which are added programmatically) if the device version is about 7.0"* – George Nov 04 '13 at 11:06
  • @congliu : It should give alignment issue if you run the application in lower version. check with the device which have IOS version less then 7.0 or check in simulator. – Ganapathy Nov 05 '13 at 03:46
  • @congliu: See by step 1 screen shot. Inspector bundle (Right side of the xcode) -> select file inspector (First one among all the 5 inspector view) -> There you can find the auto layout. – Ganapathy Nov 05 '13 at 03:57
  • 3
    gods, iOS' layout system seems such a mess. Hard-coded, version-dependent offsets? Seriously Apple? – me-- Mar 22 '14 at 01:11
  • @Ganapathy not working i have posted my images as last answer of this question please see. – Sishu Apr 07 '14 at 12:29
  • unfortunately, cannot use your approach - y origin is disabled, unless I add another view to my view and move all elements into it, now that's view y origin is editable. :( – Boris Gafurov Oct 15 '14 at 20:45
  • OR I have to do that y origin and delta adj for each element in the view, cause those are editable, it is awful way of dealing with "improvements" in new iOS. – Boris Gafurov Oct 16 '14 at 01:28
15

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;
   }
Vizllx
  • 9,135
  • 1
  • 41
  • 79
  • Its very simple. You can under that with in first 4 lines. For details description i have added the screen short. I have search for more than a hours but **no one suggest to add sub view in root view controller** to get ride of this issue. **Its better to handle the frames programmatically in case of adding the sub view unwantedly**. thas it. – Ganapathy Dec 02 '13 at 05:52
  • **As per your answer : status bar will overlaps but not the main view. It will overlap the customized view that you have added. My question is how to avoid the status bar overlap.** hope you understand. – Ganapathy Dec 02 '13 at 05:58
  • Use of undeclared identifier 'kDeviceiPad' – Moob Feb 07 '14 at 12:48
  • @Moob -"kDeviceiPad" is nsuserdefault which checks wether you are using a ipad or not.. U can write your own code to check iPad. – Vizllx Feb 26 '14 at 06:34
  • 1
    why don't you change your fixed width to self.window.frame.size.width, that why you don't have to check for device type – Tung Do Jan 06 '15 at 02:27
6
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];

    self.window.rootViewController = self.viewController;

 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {

        [application setStatusBarStyle:UIStatusBarStyleLightContent];
         [application setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];

        self.window.clipsToBounds =YES;            
        self.window.frame =CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20);
    }


   [self.window makeKeyAndVisible];
    return YES;
}

set the following to info.plist

View controller-based status bar appearance = NO;

iEinstein
  • 2,100
  • 1
  • 21
  • 32
John
  • 734
  • 3
  • 14
  • 30
3

Hear we can do this for all views at once

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{
// Notification for the orientaiton change
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(applicationDidChangeStatusBarOrientation:)
                                             name:UIApplicationDidChangeStatusBarOrientationNotification
                                           object:nil];

// Window framing changes condition for iOS7 or greater
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    statusBarBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, -20, self.window.frame.size.width, 20)];//statusBarBackgroundView is normal uiview
    statusBarBackgroundView.backgroundColor = [UIColor colorWithWhite:0.000 alpha:0.730];
    [self.window addSubview:statusBarBackgroundView];
    self.window.bounds = CGRectMake(0, -20, self.window.frame.size.width, self.window.frame.size.height);
}
// Window framing changes condition for iOS7 or greater

self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];


return YES;
}

And While we are using orientation we can add below method in app delegate to set it via orientation.

- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    statusBarBackgroundView.hidden = YES;
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    int width = [[UIScreen mainScreen] bounds].size.width;
    int height = [[UIScreen mainScreen] bounds].size.height;

    switch (orientation) {
        case UIInterfaceOrientationLandscapeLeft:
            self.window.bounds =  CGRectMake(-20,0,width,height);
            statusBarBackgroundView.frame = CGRectMake(-20, 0, 20, height);
            break;
        case UIInterfaceOrientationLandscapeRight:
            self.window.bounds =  CGRectMake(20,0,width,height);
            statusBarBackgroundView.frame = CGRectMake(320, 0, 20, height);
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            statusBarBackgroundView.frame = CGRectMake(0, 568, width, 20);
            self.window.bounds =  CGRectMake(0, 20, width, height);
            break;
        default:
            statusBarBackgroundView.frame = CGRectMake(0, -20, width, 20);
            self.window.bounds =  CGRectMake(0, -20, width, height);
            break;
    }
    statusBarBackgroundView.hidden = NO;
}
}

You should Add below navigation controller category for it

.h

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@interface UINavigationController (iOS6fix)

@end

.m

#import "UINavigationController+iOS6fix.h"
@implementation UINavigationController (iOS6fix)  

-(BOOL)shouldAutorotate
{
      return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
      return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
     return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end
Bhavin Bhadani
  • 22,224
  • 10
  • 78
  • 108
sinh99
  • 3,909
  • 32
  • 32
3

To hide status bar in ios7 follow these simple steps :

In Xcode goto "Resources" folder and open "(app name)-Info.plist file".

  • check for "View controller based status bar appearance" key and set its value "NO"
  • check for "Status bar is initially hidden" key and set its value "YES"

If the keys are not there then you can add it by selecting "information property list" at top and click + icon

Mandeep Pasbola
  • 2,631
  • 2
  • 26
  • 50
3

MUCH MUCH MUCH simpler answer:

Align the top of your view to the "top layout guide", but control-dragging "Top Layout Guide" to your view and setting the "vertical" constraint. See this answer for a picture reference.

The way it works is - the "Top Layout Guide" will automagically ajust itself for when the status bar is or is not there, and it will all work - no coding required!

P.S. In this particular example, the background showing through at the bottom should also be resolved by setting an appropriate vertical constraint of the view's bottom, to it's superview, or whatever...

Community
  • 1
  • 1
Brad
  • 11,262
  • 8
  • 55
  • 74
1

With Salesforce SDK 2.1 (Cordova 2.3.0) we had to do the following to get the status bar appear on the initial load of the App and coming back from the background (iPhone and iPad):

Contrarily to other solutions posted here, this one seems to survive rotation of the device.

1-Create a category of theSFHybridViewController

#import "SFHybridViewController+Amalto.h"

@implementation SFHybridViewController (Amalto)

- (void)viewWillAppear:(BOOL)animated
    {
        //Lower screen 20px on ios 7
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
            CGRect viewBounds = self.view.bounds;
            viewBounds.origin.y = 20;
            viewBounds.size.height = viewBounds.size.height - 20;
            self.webView.frame = viewBounds;
        }

    [super viewWillAppear:animated];
    }

    - (void)viewDidLoad
    {

        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
            CGRect viewBounds = self.view.bounds;
            viewBounds.origin.y = 20;
            viewBounds.size.height = viewBounds.size.height - 20;
            self.webView.frame = viewBounds;
        }
        [super viewDidLoad];
    }

@end

2-Add to AppDelegate.m imports

#import "SFHybridViewController+Amalto.h"

3-Inject at the end of of method didFinishLaunchingWithOptions of AppDelegate

//Make the status bar appear
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {

    [application setStatusBarStyle:UIStatusBarStyleLightContent];
    [application setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
}

4-Add to App-Info.plist the property

View controller-based status bar appearance with value NO

Bruno Grieder
  • 28,128
  • 8
  • 69
  • 101
1

i solved this by using below code

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

       if ([UIDevice currentDevice].systemVersion.floatValue>=7) {
        CGRect frame = self.window.frame;
       frame.size.width -= 20.0f;
      frame.origin.x+= 20.0f;
       self.window.frame = frame;
    }


 if(portrait)

    if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 7.0) {
    [application setStatusBarStyle:UIStatusBarStyleLightContent];

    CGRect frame = self.window.frame;
    frame.origin.y += 20.0f;
    frame.size.height -= 20.0f;
    self.window.frame = frame;
}
return YES;

 }
user2230971
  • 287
  • 1
  • 7
  • 22
1
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

 if (_kisiOS7)
    {
        [[UINavigationBar appearance] setBarTintColor:_kColorFromHEX(@"#011C47")];
    }
    else
    {
        [[UINavigationBar appearance] setBackgroundColor:_kColorFromHEX(@"#011C47")];
        [[UINavigationBar appearance] setTintColor:_kColorFromHEX(@"#011C47")];
    }
Mubin Shaikh
  • 374
  • 4
  • 9
1

There are several different ways. One approach is to use .plist file

  • Add a new key "View controller-based status bar appearance" and set value as "NO".
  • Add another key "Status bar is initially hidden" and set value as "YES".

This will hide status bar throughout project.

Screenshot for approach

Jayprakash Dubey
  • 35,723
  • 18
  • 170
  • 177
1

just set the following code in viewWillAppear.

 if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
    self.edgesForExtendedLayout = UIRectEdgeNone;
 }
Bhavin Bhadani
  • 22,224
  • 10
  • 78
  • 108