iPhone的UIViewController进入状态栏下方

10

我有一个UIView和一个UIController视图。我的标准视图大小是320x460。在applicationDidFinishLaunching中,我执行以下操作:

[window addSubview:[controller view]];

奇怪的是,UIView在状态栏下面(就像缺少连接线一样)。然而,如果我将iPhone旋转到侧面,然后再转回来,它就可以正常显示了。

这是预期的行为吗(我猜可以通过设置偏移量来解决它),还是我的操作有问题?


尝试模拟界面元素? - Jacob Relkin
我在窗口、控制器和视图上启用了模拟状态栏,但没有成功...当应用程序在 iPhone 或 XCode 模拟器中启动时,布局会出现错误。然而,在 InterfaceBuilder 的模拟器中运行良好。 - Mantas
12个回答

18

当使用presentModalViewController显示UIViewController时,我遇到了这个问题。

你可以在视图出现后手动调整控制器的视图大小来解决它:

- (void) viewDidAppear: (BOOL) animated {
    //manually adjust the frame of the main view to prevent it from appearing under the status bar.
    UIApplication *app = [UIApplication sharedApplication];
    if(!app.statusBarHidden) {
        [self.view setFrame:CGRectMake(0.0,app.statusBarFrame.size.height, self.view.bounds.size.width, self.view.bounds.size.height - app.statusBarFrame.size.height)];
    }
}

4
跟进:我看到的最好解决方案是打开您视图控制器的nib文件,选择主视图,在“模拟用户界面元素”下将“状态栏”选项设置为除“未指定”以外的任何选项。我无法解释内部值发生了什么变化,只知道这解决了我的应用程序问题。如果您这样做,您就不需要使用我之前答案中的代码。 - Nick Baicoianu
app.statusBarFrame.size.height 返回 0. :( - Gik
更正(关于我的评论):如果在执行[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:NO];之类的操作之前执行[[UIApplication sharedApplication] statusBarFrame].size.height ,它会返回0。但是在此之后,它将返回20. statusbarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height; // statusbarHeight == 20 - Gik

8
我认为你的问题在于当你向窗口添加视图时,需要注意状态栏的状态并进行相应的调整:
if showing the status bar :
   [controller view].frame = CGRectMake(0, **20**, 320, 460);
else 
   [controller view].frame = CGRectMake(0, 0, 320, **480**);

这就是为什么 IB 会显示一栏虚拟状态栏的原因。

谢谢。我已经使用它来解决问题了。我只是不确定那是否是常规的修复方式。 - Mantas
很好的修复,但是顺便提一下,20 应该是 CGRectMake 的第二个参数,而不是第一个 :)。 - makdad

5

今天我添加了这个问题。结果发现我在ViewController的属性检查器中勾选了“想要全屏”。

关闭“想要全屏”解决了这个问题。


3

修复窗口对我没用,因为我有一个模态视图。这是一个UIModalPresentationCurrentContext模态视图。好吧,这是对我有用的东西。在让它起作用之前,我在网上搜索了很多。

我无法从父视图中移动view.frame。然而,在viewWillAppear中,我可以将其向下移动:

- (void)viewWillAppear:(BOOL)animated
{
    // Move down to compensate for statusbar
    CGRect frame = parentView.navCon.view.frame;
    frame.origin.y = [UIApplication sharedApplication].statusBarFrame.size.height;
    parentView.navCon.view.frame = frame;
}

1
那是“作弊”!;-) 你应该“查找”状态栏的高度,而不是将其“硬编码”为20。如果苹果决定将其更改为25呢?那么你就会偏移5像素! - Gik

3

最终,我找到了这个解决方案。对于都有效:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    // Allocate view controller and load nib file
    if (isIPhone) {
        self.mainViewController = [[[tfdMainViewController_iPhone alloc] initWithNibName:@"tfdMainViewController_iPhone" bundle:nil] autorelease];
    } else {
        self.mainViewController = [[[tfdMainViewController_iPad alloc] initWithNibName:@"tfdMainViewController_iPad" bundle:nil] autorelease];
    }

    // Offset correction (iPhone bug?)
    CGRect r = self.mainViewController.view.frame; 
    r = CGRectOffset(r, 0, [UIApplication sharedApplication].statusBarFrame.size.height);
    [self.mainViewController.view setFrame:r];  

    [window addSubview: self.mainViewController.view];
    [self.window makeKeyAndVisible];
    return YES;
}

顺便提一下,出于某种原因,视图的高度是正确的:480(iPhone纵向模式下的屏幕高度)-20(状态栏)=460,但无法设置垂直偏移量。这是非常奇怪的行为,看起来像是一个漏洞。


1
如果您正在使用Interface Builder的“模拟用户界面元素”,那么您还需要确保在MainWindow nib中设置了“从NIB调整视图大小”的标志。

1

0

对于 Xamarin.iOS,它将是:

if (UIApplication.SharedApplication.StatusBarHidden == false)
{
   var statusBarHeight = UIApplication.SharedApplication.StatusBarFrame.Height;
   View.Frame = new CoreGraphics.CGRect(0, statusBarHeight, View.Frame.Width, View.Frame.Height - statusBarHeight);
}

0

我更喜欢使用UINavigationController来包装UIViewController,然后将NavigationBarHidden设置为UINavigationController。这是完美的解决方案,因为UINavigationController确实处理iOS 7中状态栏的高度。

以下是我的代码和屏幕截图。

UINavigationController *wrapNavController = [[UINavigationController alloc] initWithRootViewController:yourViewController] ;

[wrapNavController setNavigationBarHidden:YES] ;

0
你是否在添加子视图后手动设置应用程序栏隐藏属性?我不认为是这种情况,但如果在首次加载视图时将其设置为无,则会按照没有应用程序栏的方式进行布局,如果您随后将状态栏设置为未隐藏,则它将弹出在您的视图之上。
一个可能的解决方案是在添加子视图后使用[[controller view] setNeedsLayout];,或者可能是[window layoutSubviews];。我从来没有在使用它们来解决布局问题方面取得过很大的成功,但由于它在旋转后起作用,所以值得一试。

我从未在任何时候设置应用程序栏隐藏。那些重新布局的事情没有帮助... - Mantas

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