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.
25 Answers
You can resolve this issue if you are using storyboards, as in this question: iOS 7 - Status bar overlaps the view
If you're not using storyboard, then you can use this code in your AppDelegate.m
in did finishlaunching
:
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-20);
}
Also see this question: Status bar and navigation bar issue in IOS7
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];
}
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!
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);
}
}
}
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];
}
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.
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.
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! :)
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
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];
}
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.
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;
}
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 )];
}
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';
}