ChatGPT解决这个技术问题 Extra ChatGPT

iOS 7 Status bar with Phonegap

In iOS 7, Phonegap applications will appear underneath the status bar. This can make it difficult to click on buttons/menus that have been placed at the top of the screen.

Is there someone who knows a way to fix this status bar issue on iOS 7 in a Phonegap application?

I've tried to offset the entire web page with CSS but it doesn't seem to work. Is there a way to like offset the entire UIWebView or just make the status bar behave like it did in iOS6?

Thanks

what exactly is the "status bar issue" ? Any sample code to reproduce?
@ShivanRaptor With iOS 7, the status bar is now part of the view, so if you have stuff that was at the top of the screen with previous iOS versions, it is now underneath the status bar, not automatically pushed right below it, which can cause some problems. My suggestion would be to create a wrapper for your content, and set a margin-top of 20px.
@AndrewLively - This doesn't really work when the page is scrolling, is there any way to move the UIWebView?

D
Dharmesh Dhorajiya

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];
}

Is anyone else using this with the In App Browser plugin? If I configure the In App Browser as "presentationstyle=fullscreen", a blank bottom margin is appearing after the browser is closed. It looks like the margin is the same height as the InAppBrowser toolbar. Setting the presentationtype to "pagesheet" fixes this on iPad, but iPhone seems to always use "fullscreen". Any workarounds?
Very grateful for the answer -- however the same issue applies to the PhoneGap inApp browser -- it overlays the status bar as well. Any ideas for that?
Yes, we use an older version of Cordova (2.3.0), and to fix this you'll have to set webViewBounds.origin.y = 20; in createViewsWithOptions. Also, see if the background color is being set and play around with that. Do a version check for iOS7 and above, just as in this excellent answer from LudWig Kristoffersson.
Also - if you're using the InAppBrowser, the view will re-initialize each time you return. So it would be prudent to add a flag that says it's already been run to your MainViewController.m.
Because this code runs in viewWillAppear, you'll run into issues with this solution if your PhoneGap/Cordova app displays other native views (like the camera capture dialog) and returns to this view. The fix for me was to initialize 'viewBounds' to '[self.view bounds]' instead of '[self.webView bounds]'.
A
Alex L

In addition to Ludwig Kristoffersson's resize fix, I recommend changing status bar color:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    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;
    }
    self.view.backgroundColor = [UIColor blackColor];
}
-(UIStatusBarStyle)preferredStatusBarStyle{
    return UIStatusBarStyleLightContent;
}

Working Great :) Thanks a Lot :)
Perfect - this was the better solution for me.
This fix works locally after an Xcode build, but not after I do a phonegap build. Any ideas? I have an ios app built with phonegap 2.9
This solution works but I had a problem with fullscreen videos and I found this other one and it fixed my problem zsprawl.com/iOS/2013/10/fixing-the-phonegap-status-bar-in-ios7
@KirankumarSripati actually my last solution was this I hope thiw works for you NSInteger screenSize = 0; //Global if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { CGRect viewBounds = [self.webView bounds]; viewBounds.origin.y = 20; if(screenSize == 0) { viewBounds.size.height = viewBounds.size.height - 20; screenSize = viewBounds.size.height; } self.webView.frame = viewBounds; } I did that because my app was resizing everytime I entered fullscreen
x
xdemocle

please, install that plugin for phonegap: https://build.phonegap.com/plugins/505

And use the correct setting like below, to control the overlay of the webview:

<preference name="StatusBarOverlaysWebView" value="false" />

For me, with Phonegap 3.3.0 it works.

More information, on the Github project page: https://github.com/phonegap-build/StatusBarPlugin


Thanks a lot for this answer!! I was trying with this plugin: build.phonegap.com/plugins/715 , the problem is that names are the same. But never works for me. Thanks a lot!!
To be honest, I don't remember if I tried before this one mentioned by you.
m
markmarijnissen

To hide statusbar, add the following code in the file MainViewController.m under the function -(void)viewDidUnload

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

This does the job. It will hide the statusbar making your app full screen. I only tested this on the simulator but will report back later when I run a build on my iPhones and iPads.
Works for me on iOS on an iPad 2
This works fine on iPad Air iOS 7.1.2 and there is no need for any changes or plugins. Great answer, thank you!
This totally ignores everything that Apple says about 'immersive fullscreen mode" in the Human Interface Guidelines... just because you're using a wrapper on top of iOS doesn't mean you can ignore the design patterns... :/
p
peterh

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:

In MainViewController.h:

@interface MainViewController : CDVViewController
@property (atomic) BOOL viewSizeChanged;
@end

In MainViewController.m:

@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');
}

Here is the viewport I use for other versions:

<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0" />

And all works well now.


Any method without Jquery @dieppe
simply add this code to - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info {} method inside CDVCamera.m that solves camera issue also. NSLog(@"CLOSED CAMERA"); [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
Man, I don't know the words to say thank you! I've been struggling with the 20px shrink problem with camera, and couldn't find the solution until now...
d
dk123

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

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

This works for me without problem.


For me, this works in the simulator with a local build, but not in the iPad with a remote build. Using PG 3.1 for the build and iOS7 on the simulator and the iPad.
@PerQuestedAronsson You might want to try building it locally on to the iPad. I'm working with an iPad iOS7 with phonegap 3.1 without problem.
t
trejder

For Cordova 3.1+, there is a plugin that deals with the change in behaviour of the status bar for iOS 7+.

This is nicely documented here, including how the status bar can be reverted to its pre-iOS7 state.

To install the plugin, run:

cordova plugin add org.apache.cordova.statusbar

Then add this to config.xml

<preference name="StatusBarOverlaysWebView" value="false" />
<preference name="StatusBarStyle" value="default" />

You can also set the StatusBar color which defaults to black: <preference name="StatusBarBackgroundColor" value="#000000" /> See: plugins.cordova.io/#/package/org.apache.cordova.statusbar
For Cordova 5+, the plugin has been renamed: cordova plugin add cordova-plugin-statusbar
m
mayconbelfort

I solve my problem by installing the org.apache.cordova.statusbar and adding in my top config.xml:

<preference name="StatusBarOverlaysWebView" value="false" /> 
<preference name="StatusBarBackgroundColor" value="#000000" />
<preference name="StatusBarStyle" value="lightcontent" />

These configurations only works for iOS 7+

Reference: http://devgirl.org/2014/07/31/phonegap-developers-guid/


P
Philippe Monnet

See the new Cordova StatusBar plugin which addresses that exact issue. http://docs.icenium.com/troubleshooting/ios7-status-bar#solution option #3


R
Ryan

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.

if(window.device && parseFloat(window.device.version) >= 7){
  document.body.classList.add('fix-status-bar');
}

C
Community

Ludwig's answer worked for me.

For anyone who used his answer and is now looking to change the color of the white margin (may seem trivial, but had me stumped), see this:

How can I change the UIWebView background color after sliding down UIWebView to fix the iOS7 status bar overlay issue?


t
tipycalFlow

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:

- (void)viewDidLoad
{
  [super viewDidLoad];

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

This solution won't leave a black bar on top for iOS 7.0 and above, which a modern iOS user will find odd and old.


E
Ehsan

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! :)


This code looks to work great to hide the status bar and fix the issue, i also looked around a bit yesterday and found a peace of code that essentially resized the UIWebView and moved it down I added this as an answer as well :)
That's great. My code is only using a simple and easy way for doing it! All of us are doing the same thing with different methods :)
A
Arjun T Raj

if we use camera plugin for image gallery, status bar will come back so to fix that issue please add this line

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

to

- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info {...}

function inside CVDCamera.m in plugins list


R
RahulSalvikar

Write the following code inside AppDelegate.m in didFinishLaunchingWithOptions event at starting.

CGRect screenBounds = [[UIScreen mainScreen] bounds]; // Fixing status bar ------------------------------- NSArray *vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."]; if ([[vComp objectAtIndex:0] intValue] >= 7) { // iOS 7 or above CGRect newWebViewBounds = CGRectMake( 0, 20, screenBounds.size.width, screenBounds.size.height-20 ); screenBounds = newWebViewBounds; } // ------------------------------- Fixing status bar End

And fix for above iOS 7 and above.


m
matb33

To keep the status bar visible in portrait but hide it in landscape (i.e. fullscreen), try the following:

In MainViewController.h:

@interface MainViewController : CDVViewController
@property (atomic) NSInteger landscapeOriginalSize;
@property (atomic) NSInteger portraitOriginalSize;
@end

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).


S
Shashank Agrawal

First of all, Add the Device plugin in you project. Plugin Id is: org.apache.cordova.device and repository is: https://github.com/apache/cordova-plugin-device.git

After that use this function and call it on every page or screen:-

function mytopmargin() {
    console.log("PLATform>>>" + device.platform);
    if (device.platform === 'iOS') {
        $("div[data-role='header']").css("padding-top", "21px");
        $("div[data-role='main']").css("padding-top", "21px");
    } else {
        console.log("android");
    }
}

N
Niv Asraf

The best way to control Status Bar background - 2017

After ongoing frustration, a lot of search on the Internet, these are the steps you need to take:

Make sure that you use Status Bar Plugin Add this setting to your config.xml:

< preference name="StatusBarOverlaysWebView" value="false" />

Use the following code on onDeviceReady StatusBar.show(); StatusBar.overlaysWebView(false); StatusBar.backgroundColorByHexString('#209dc2');

It's works for me in iOS & Android.

Good luck!