iOS 7状态栏与Phonegap的问题

91

在iOS 7中,Phonegap应用程序将出现在状态栏下面。这可能会使位于屏幕顶部的按钮/菜单难以点击。

是否有人知道如何在Phonegap应用程序中修复iOS 7上的状态栏问题?

我已经尝试使用CSS偏移整个网页,但似乎不起作用。是否有一种方法可以像在iOS 6中一样改变整个UIWebView的偏移量或只是让状态栏的行为像以前一样?

谢谢


“状态栏问题”到底是什么?有没有可以复现的示例代码? - Raptor
1
@ShivanRaptor 在iOS 7中,状态栏现在是视图的一部分,因此如果您有之前iOS版本中位于屏幕顶部的内容,它现在会出现在状态栏下面,而不是自动推到其正下方,这可能会导致一些问题。我的建议是为您的内容创建一个包装器,并设置20像素的margin-top。 - Andrew Lively
@AndrewLively - 当页面滚动时,这并不真正起作用,有没有办法移动UIWebView? - Luddig
18个回答

142

我在另一个帖子上找到了答案,但为了避免其他人产生疑问,在这里回答一下这个问题。

只需将MainViewController.m中的viewWillAppear替换为以下内容:

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

9
还有其他人在使用这个In App Browser插件吗?如果我将In App Browser配置为“presentationstyle=fullscreen”,浏览器关闭后会出现一个空白底部边距。看起来这个边距的高度与InAppBrowser工具栏一样高。在iPad上将presentationtype设置为“pagesheet”可以解决此问题,但iPhone似乎始终使用“fullscreen”。有什么解决方法吗? - Paul
2
是的,我们使用较旧版本的Cordova(2.3.0),要解决这个问题,您需要在createViewsWithOptions中设置webViewBounds.origin.y = 20;。此外,请检查背景颜色是否已设置并进行调整。像LudWig Kristoffersson的这个出色答案一样,在iOS7及以上版本中进行版本检查。 - hnilsen
3
此外 - 如果您正在使用InAppBrowser,每次返回时视图都会重新初始化。因此,在MainViewController.m中添加一个标志,表示它已经运行过是明智的选择。 - hnilsen
14
因为这段代码运行在viewWillAppear中,如果你的PhoneGap/Cordova应用程序显示其他本机视图(如相机捕获对话框)并返回到此视图,则会遇到问题。我的解决方法是将'viewBounds'初始化为'[self.view bounds]'而不是'[self.webView bounds]'。 - Chris Karcher
1
我遇到了和Chris一样的问题。我只是把解决方案放在webViewDidFinishLoad中...这样它只会被调用一次。当我把它放在viewWillAppear中时,每次尝试使用相机时视图的高度都会缩小20像素。 - bmurmistro
显示剩余10条评论

37

除了Ludwig Kristoffersson的调整大小修复外,我建议更改状态栏颜色:

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

1
工作得很好 :) 非常感谢 :) - rkaartikeyan
完美 - 这对我来说是更好的解决方案。 - David Daudelin
这个修复在Xcode构建后本地有效,但在进行phonegap构建后无效。有什么想法吗?我使用phonegap 2.9构建了一个iOS应用程序。 - DemitryT
这个解决方案可行,但是我在全屏视频方面遇到了问题,后来我找到了另一个解决方案并解决了我的问题。http://zsprawl.com/iOS/2013/10/fixing-the-phonegap-status-bar-in-ios7/ - magorich
@magorich 我试过了,但它会隐藏屏幕底部的20像素。 - Kirankumar Sripati
1
@KirankumarSripati,我的上一个解决方案是这样的,我希望这对你有用。NSInteger screenSize = 0; //全局变量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; }我这样做是因为每次进入全屏模式时,我的应用程序都会调整大小。 - magorich

22

非常感谢您的回答!!我一直在尝试使用这个插件:https://build.phonegap.com/plugins/715,但问题是名称相同。但是对我来说从未起作用。非常感谢!! - Jabel Márquez
说实话,我不记得之前是否尝试过你提到的这个。 - xdemocle

20
在文件MainViewController.m-(void)viewDidUnload函数下,添加以下代码以隐藏状态栏。
- (BOOL)prefersStatusBarHidden
{
    return YES;
}

这可以完成任务。它将隐藏状态栏,使您的应用程序全屏。我只在模拟器上测试过,但稍后在我的iPhone和iPad上运行构建时会回报。 - Rob Evans
在我的 iPad 2 上的 iOS 上运行良好。 - Mark Williams
这在iPad Air iOS 7.1.2上运行良好,不需要任何更改或插件。非常好的答案,谢谢! - Scriptlabs
这完全忽略了苹果在人机界面指南中关于“沉浸式全屏模式”的所有说明...仅仅因为你在iOS上使用了一个包装器并不意味着你可以忽略设计模式... :/ - jesses.co.tt

15

这个答案对我很有用,但是我需要稍微修改一下才能让它与相机插件(和其他插件)以及一个带有“height = device-height”的viewport meta标签一起使用(如果不设置高度部分,则会导致键盘在我的情况下出现在视图上,沿途隐藏一些输入)。

每次打开相机视图并返回到您的应用程序时,viewWillAppear方法将被调用,并且您的视图将缩小20px。

此外,viewport的device-height将包括额外的20px,使内容可滚动,并比webview高20px。

以下是相机问题的完整解决方案:

In MainViewController.h:

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

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

现在针对视口问题,在您的deviceready事件监听器中添加以下内容(使用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');
}

以下是我用于其他版本的视口:

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

现在一切正常。

没有使用Jquery的任何方法 @dieppe - Arjun T Raj
只需将以下代码添加到CDVCamera.m中的-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info {}方法中,即可解决相机问题。NSLog(@"CLOSED CAMERA"); [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone]; - Arjun T Raj
哎呀,我真的不知道该说什么感谢的话了!我一直在摄像头20像素缩小的问题上苦苦挣扎,一直找不到解决办法,直到现在... - tuks

6

对于Cordova 3.1+,有一个插件可以处理iOS 7+状态栏行为的更改。

这个文档很好地记录在这里,包括如何将状态栏恢复到其iOS7之前的状态。

要安装插件,请运行:

cordova plugin add org.apache.cordova.statusbar

然后将以下内容添加到config.xml中。
<preference name="StatusBarOverlaysWebView" value="false" />
<preference name="StatusBarStyle" value="default" />

你也可以设置状态栏的颜色,它默认为黑色:参见:http://plugins.cordova.io/#/package/org.apache.cordova.statusbar - ezzadeen
2
对于 Cordova 5+,该插件已更名为:cordova plugin add cordova-plugin-statusbar。 - raider33

6

尝试进入XCode中应用程序的(应用程序名称)-Info.plist文件,并添加以下键:

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

这对我来说没有问题。

对我来说,在模拟器上进行本地构建可以正常工作,但是在 iPad 上使用远程构建就无法正常工作。构建时使用 PG 3.1,模拟器和 iPad 均使用 iOS7。 - Per Quested Aronsson
@PerQuestedAronsson 你可能想尝试在iPad上本地构建它。我正在使用iPad iOS7和PhoneGap 3.1,没有任何问题。 - dk123

5

我通过安装org.apache.cordova.statusbar和在我的顶部的config.xml中添加以下内容来解决了我的问题:

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

这些配置仅适用于iOS 7及以上版本。

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


3

1

另一种方法是实现向后兼容。根据的HTML(顶部额外20像素的边距)来展示全屏效果,并在iOS < 7.0中去除这个额外的边距。类似于以下在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;
  }
}

这个解决方案不会在iOS 7.0及以上版本上留下黑色的顶部栏,对于现代iOS用户来说,这样会显得奇怪和过时。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接