I use the following piece of code to add a class to the body, if iOS7 is detected. I then style that class to add a 20px margin at the top of my container. Make sure you have the "device" plugin installed and that this code is inside the "deviceready" event.
From reading around, I've heard that the next update to Phonegap (3.1 I believe) will better support the changes to iOS7's status bar. So this may just be needed as a short term fix.
I found an answer on another thread, but I'll answer the question in case someone else wonders.
Just replace the viewWillAppear in MainViewController.m with 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 = 20;
viewBounds.size.height = viewBounds.size.height - 20;
self.webView.frame = viewBounds;
}
[super viewWillAppear:animated];
}
Answer https://stackoverflow.com/a/19249775/1502287 worked for me, but I had to change it a bit to make it work with the camera plugin (and potentially others) and a viewport meta tag with "height=device-height" (not setting the height part would cause the keyboard to appear over the view in my case, hiding some inputs along the way).
Each time you would open the camera view and go back to your app, the viewWillAppear method would be called, and your view would shrink by 20px.
Also, the device-height for the viewport would include the 20 extra px, rendering the content scrollable and 20px higher than the webview.
Here is the complete solution for the camera problem:
@implementation MainViewController
@synthesize viewSizeChanged;
[...]
- (id)init
{
self = [super init];
if (self) {
// On init, size has not yet been changed
self.viewSizeChanged = NO;
// Uncomment to override the CDVCommandDelegateImpl used
// _commandDelegate = [[MainCommandDelegate alloc] initWithViewController:self];
// Uncomment to override the CDVCommandQueue used
// _commandQueue = [[MainCommandQueue alloc] initWithViewController:self];
}
return self;
}
[...]
- (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 not already done
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7 && !self.viewSizeChanged) {
CGRect viewBounds = [self.webView bounds];
viewBounds.origin.y = 20;
viewBounds.size.height = viewBounds.size.height - 20;
self.webView.frame = viewBounds;
self.viewSizeChanged = YES;
}
[super viewWillAppear:animated];
}
Now for the viewport problem, in your deviceready event listener, add this (using jQuery):
if (window.device && parseFloat(window.device.version) >= 7) {
$(window).on('orientationchange', function () {
var orientation = parseInt(window.orientation, 10);
// We now the width of the device is 320px for all iphones
// Default height for landscape (remove the 20px statusbar)
var height = 300;
// Default width for portrait
var width = 320;
if (orientation !== -90 && orientation !== 90 ) {
// Portrait height is that of the document minus the 20px of
// the statusbar
height = document.documentElement.clientHeight - 20;
} else {
// This one I found experimenting. It seems the clientHeight
// property is wrongly set (or I misunderstood how it was
// supposed to work).
// I don't know if it is specific to my setup.
width = document.documentElement.clientHeight + 20;
}
document.querySelector('meta[name=viewport]')
.setAttribute('content',
'width=' + width + ',' +
'height=' + height + ',' +
'initial-scale=1.0,maximum-scale=1.0,user-scalable=no');
})
.trigger('orientationchange');
}
Another way is going backward compatible. Make the HTML according to iOS 7 (with an extra 20px margin on top) to give that full screen look and cut that extra margin off for iOS < 7.0. Something like the following in MainViewController.m:
@implementation MainViewController
@synthesize landscapeOriginalSize;
@synthesize portraitOriginalSize;
...
- (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.
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)orientationChanged:(NSNotification *)notification {
[self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}
- (void)viewDidDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
CGRect frame = self.webView.frame;
switch (orientation)
{
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationPortraitUpsideDown:
{
if (self.portraitOriginalSize == 0) {
self.portraitOriginalSize = frame.size.height;
self.landscapeOriginalSize = frame.size.width;
}
frame.origin.y = statusBarFrame.size.height;
frame.size.height = self.portraitOriginalSize - statusBarFrame.size.height;
}
break;
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
{
if (self.landscapeOriginalSize == 0) {
self.landscapeOriginalSize = frame.size.height;
self.portraitOriginalSize = frame.size.width;
}
frame.origin.y = 0;
frame.size.height = self.landscapeOriginalSize;
}
break;
case UIInterfaceOrientationUnknown:
break;
}
self.webView.frame = frame;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// Change this color value to change the status bar color:
self.view.backgroundColor = [UIColor colorWithRed:0/255.0f green:161/255.0f blue:215/255.0f alpha:1.0f];
}
This is a combination of what I've found in this and linked StackOverflow discussions, some code from the Cordova StatusBar plugin (so as not to hardcode the 20px value), and some incantations on my part (I'm not an iOS dev so I fumbled my way to this solution).