[iphone] iOS 7 status bar overlapping UI

I recently upgraded to xcode 5 and when I run my app in the iOS simulator the splash screen overlaps the status bar and when you are in the app the status bar overlaps onto elements on my app, like a back button I have on the top left hand corner of my app. I build my app using phonegap 2.9. Any ideas how i can get this to render correctly.

splashscreen

UI

This question is related to iphone cordova ios7 xcode5

The answer is


I've got a problem opening the inApp browser with phonegap. Gimi's fix worked well, but everytime I opened the inApp browser the screen was shrinked at the bottom. So I've added an if statement to check if the webview's y origin was 0. The inApp browser hasn't the y origin 0 anymore so it solved my problem.

// ios 7 status bar fix
- (void)viewWillAppear:(BOOL)animated
{
    // View defaults to full size.  If you want to customize the view's size, or its subviews (e.g. webView),
    // you can do so here.
    //Lower screen 20px on ios 7
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        if(self.webView.frame.origin.y == 0) {
            CGRect viewBounds = [self.webView bounds];
            viewBounds.origin.y = 20;
            viewBounds.size.height = viewBounds.size.height - 20;
            self.webView.frame = viewBounds;
        }
    }

    [super viewWillAppear:animated];
}

The solution is not really mine but I can't find the source. Hope it helps!


From Apple iOS7 transition Guide,

Specifically,

self.automaticallyAdjustsScrollViewInsets = YES;
self.edgesForExtendedLayout = UIRectEdgeNone;

works for me when I don't want to overlap and I have a UITableViewController.


If you're using Cordova with Sencha Touch and you're using the normal Sencha Touch navigation/title bars, you can just stretch the navbar and reposition the content within the navbar so it looks at home on iOS 7. Just add this into app.js (after your last Ext.Viewport.add line) :

// Adjust toolbar height when running in iOS to fit with new iOS 7 style
if (Ext.os.is.iOS && Ext.os.version.major >= 7) {
  Ext.select(".x-toolbar").applyStyles("height: 62px; padding-top: 15px;");
}

(Source: http://lostentropy.com/2013/09/22/ios-7-status-bar-fix-for-sencha-touch-apps/)

This is a bit hacky, I know, but it saves dealing with it at the Objective-C level. It won't be much good for those not using Sencha Touch with Cordova, though.


Write the following code inside AppDelegate.m in didFinishLaunchingWithOptions event (exactly before its last line of code "return YES;" ) :

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
{
    [application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
}

I'll wait for your feedback! :)


If your developing for iOS 7 I wouldn't recommend wrapping the status bar in a black rectangle old iOS style. Just integrate it to the design for a more iOS 7 "fullscreen" look.

You can use this plugin to adjust the ink colour of the status bar, or hide it or show it in any instance of your app.

https://github.com/jota-v/cordova-ios-statusbar

The js methods are:

window.plugins.statusBar.hide();
window.plugins.statusBar.show();
window.plugins.statusBar.blackTint();
window.plugins.statusBar.whiteTint();

IMPORTANT: Also in your app plist file set UIViewControllerBasedStatusBarAppearance to NO.


Many thanks man. It worked fine on:

MAC OS X 10.9.1 - Xcode 5.0.2 - cordova 3.3 - jQuery mobile 1.3.2.


Place this code snippet in your MainViewController.m file in the phonegap project.

- (void)viewDidLayoutSubviews{

    if ([self respondsToSelector:@selector(topLayoutGuide)]) // iOS 7 or above
    {
        CGFloat top = self.topLayoutGuide.length;
        if(self.webView.frame.origin.y == 0){
            // We only want to do this once, or 
            // if the view has somehow been "restored" by other    code.
            self.webView.frame = CGRectMake(self.webView.frame.origin.x,
                                           self.webView.frame.origin.y + top,
                                           self.webView.frame.size.width,
                                           self.webView.frame.size.height-top);
        } 
    } 
}

The best approach you can use, is to resize the main view, specially if your application uses a footer.

on MainViewController.m using the viewDidLoad method, after [super viewDidLoad];

NSArray *vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
if ([[vComp objectAtIndex:0] intValue] >= 7) {
    // iOS 7 or above
    CGRect oldBounds = [self.view bounds];
    CGRect newViewBounds = CGRectMake( 0, -10, oldBounds.size.width, oldBounds.size.height-20 );
    CGRect newWebViewBounds = CGRectMake( 0, -20, oldBounds.size.width, oldBounds.size.height-40 );

    [self.view setBounds:newViewBounds];
    [self.webView setBounds:newWebViewBounds];
}

then you won't need to modify any javascript into your application


For iPhoneX

For all the answers above :

The height of the status bar in the iPhoneX is 44 and not 20


To address the issue of the status bar iOS7, we can use the following code to Cordova / PhoneGap:

function onDeviceReady() {
    if (parseFloat(window.device.version) === 7.0) {
          document.body.style.marginTop = "20px";
    }
}

document.addEventListener('deviceready', onDeviceReady, false);

Anyway Cordova 3.1 will soon fix that this and other issues for iOS7.


In .plist file set property:

<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

It hides the statusBar.


I develop for iOS7 first but in order to keep compatible with iOS6 I do exactly the opposite what Gimi suggested - in MainViewController.m I set the y origin 20px up and increase the view height by 20px:

//Lower screen 20px on ios 7

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

What I usually do is add two key-value properties to the Info.plist file.

enter image description here

The properties source code is:

enter image description here


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

        self.window.clipsToBounds =YES;
[application setStatusBarStyle:UIStatusBarStyleLightContent];
 self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20);
    }

We can also check this within our js files

if (parseFloat(window.device.version) >= 7.0) {

    $("body").addClass("ios7");
}

In .css file define a class for this

 .ios7 .ui-page, .ios7 .ui-header, .ios7 .ui-pane {
     margin-top: 17px !important;
  }

Better to have this things in info.plist

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

this makes no status bar at all.


I started to go this route, but I have my own navigation control with a core view that I slide into a frame that's usually wrapping the core with a common title bar and tabbar; no storyboard, no UINavigationController.

It started to get complicated fast, adding and subtracting the 20 pixels of the status bar. Then an epiphany.

I made a copy of the .xib file, told Xcode to show it to me as an iOS 7 layout, realigned everything, and put a single 6/7 switch in code .. instantly, everything works right, and the additional resources add only 8K to the bundle.


Some of the above answers will give you a black bar on top if you set your screen bound 20px, other will keep reduce your webview screen if you use webview.frame.size.height -20px; Try this one then, it works on any ios and no need to change css, put in inside

- (void)webViewDidFinishLoad:(UIWebView*)theWebView {

//is it IOS7 and up

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

//get the device screen size

    CGRect screenBounds = [[UIScreen mainScreen] bounds];

//reduce the height by 20px

    int x= screenBounds.size.height -20;

//set the webview top pos 20px so it is under the status bar and reduce the size by 20px

    [theWebView setFrame:CGRectMake(0, 20, theWebView.frame.size.width, x )];

}

Actually, I found Gimi's answer to be the best answer, and I've been looking a lot! Just to add to Gimi's answer, and also answer ignacio-munizaga's reply on that answer, The code will execute whenever the view appears, which means after you close an inline browser, or after camera roll etc. so I just put a bool value stating whether the size has already been adjusted.

The final code looks like:

bool sizeWasAdjusted = false;
- (void)viewWillAppear:(BOOL)animated
{
    // View defaults to full size.  If you want to customize the view's size, or its subviews (e.g. webView),
    // you can do so here.
    //Lower screen 20px on ios 7
    if (!sizeWasAdjusted && [[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        CGRect viewBounds = [self.webView bounds];
        viewBounds.origin.y = 18;
        viewBounds.size.height = viewBounds.size.height - 18;
        self.webView.frame = viewBounds;
        sizeWasAdjusted = true;
    }
    [super viewWillAppear:animated];
}

I use this code in the ViewDidLoad method.

 if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
 {
    self.edgesForExtendedLayout = UIRectEdgeNone;
 }

This works when trying to support previous iOS versions too.


Here is my approach using CSS and Javascript:

1) Define the following in your CSS:

#ios7-statusbar-fix {
    width:100%;
    height:20px;
    background-color:white;
    position:fixed;
    z-index:10000;
    margin-top:-20px;
    display:none;
}

2) Add div-container with this id as very first element after your <body>-tag:

<body>
    <div id="ios7-statusbar-fix"></div>
…

3) Filter iOS 7 devices and apply changes via Javascript:

if (navigator.userAgent.match(/(iPad.*|iPhone.*|iPod.*);.*CPU.*OS 7_\d/i)) {
        document.body.style.marginTop = '20px';
        document.getElementById('ios7-statusbar-fix').style.display = 'block';
}

Try going into the app's (app name)-Info.plist file in XCode and add the key

view controller-based status bar appearance: NO
status bar is initially hidden : YES

This seems to work for me without problem.


With the release of iOS 7.0.4, the iOS7 fix broke in my current project, as 7.0.4 works w/o the fix. So added a minor control to just run it if running minor release 3 or less.

NSArray *vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
if ([[vComp objectAtIndex:0] intValue] == 7 && [[vComp objectAtIndex:1] intValue] == 0 && [[vComp      objectAtIndex:2] intValue] <= 3 ) {
    CGRect oldBounds = [self.view bounds];
    CGRect newViewBounds = CGRectMake( 0, -10, oldBounds.size.width, oldBounds.size.height-20 );
    CGRect newWebViewBounds = CGRectMake( 0, -20, oldBounds.size.width, oldBounds.size.height-40 );
    [self.view setBounds:newViewBounds];
    [self.webView setBounds:newWebViewBounds];
}

In MainViewController.m inside: - (void)viewWillAppear:(BOOL)animated add this:

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

so the end function will look like this:


- (void)viewWillAppear:(BOOL)animated
{
    // View defaults to full size.  If you want to customize the view's size, or its subviews (e.g. webView),
    // you can do so here.
    //Lower screen 20px on ios 7
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        CGRect viewBounds = [self.webView bounds];
        viewBounds.origin.y = 18;
        viewBounds.size.height = viewBounds.size.height - 18;
        self.webView.frame = viewBounds;
    }
    [super viewWillAppear:animated];
}


Examples related to iphone

Detect if the device is iPhone X Xcode 8 shows error that provisioning profile doesn't include signing certificate Access files in /var/mobile/Containers/Data/Application without jailbreaking iPhone Certificate has either expired or has been revoked Missing Compliance in Status when I add built for internal testing in Test Flight.How to solve? cordova run with ios error .. Error code 65 for command: xcodebuild with args: "Could not find Developer Disk Image" Reason: no suitable image found iPad Multitasking support requires these orientations How to insert new cell into UITableView in Swift

Examples related to cordova

Why am I seeing net::ERR_CLEARTEXT_NOT_PERMITTED errors after upgrading to Cordova Android 8? Xcode couldn't find any provisioning profiles matching Cordova app not displaying correctly on iPhone X (Simulator) JAVA_HOME is set to an invalid directory: ionic 2 - Error Could not find an installed version of Gradle either in Android Studio cordova Android requirements failed: "Could not find an installed version of Gradle" Error: Could not find gradle wrapper within Android SDK. Might need to update your Android SDK - Android Ionic 2: Cordova is not available. Make sure to include cordova.js or run in a device/simulator (running in emulator) Cordova : Requirements check failed for JDK 1.8 or greater Can't accept license agreement Android SDK Platform 24

Examples related to ios7

Xcode: Could not locate device support files How to Apply Gradient to background view of iOS Swift App How do I hide the status bar in a Swift iOS app? Using Predicate in Swift How do I programmatically set device orientation in iOS 7? What is the height of Navigation Bar in iOS 7? Warning :-Presenting view controllers on detached view controllers is discouraged Color Tint UIButton Image iOS change navigation bar title font and color How to embed small icon in UILabel

Examples related to xcode5

OS X Framework Library not loaded: 'Image not found' "The file "MyApp.app" couldn't be opened because you don't have permission to view it" when running app in Xcode 6 Beta 4 Duplicate symbols for architecture x86_64 under Xcode iOS 7 - Failing to instantiate default view controller Undefined symbols for architecture arm64 iOS 7 status bar overlapping UI Find provisioning profile in Xcode 5 iOS 7 App Icons, Launch images And Naming Convention While Keeping iOS 6 Icons Is it possible to install iOS 6 SDK on Xcode 5? Provisioning Profiles menu item missing from Xcode 5