Iphone 视图控制器中的UINavigationController,视图顶部的间隙

Iphone 视图控制器中的UINavigationController,视图顶部的间隙,iphone,xcode,ipad,ios,interface-builder,Iphone,Xcode,Ipad,Ios,Interface Builder,我正在开发一个通用的应用程序,我正在尝试在iPhone和iPad版本之间尽可能多地共享代码。我需要使用TabBarController作为我的根视图控制器,虽然我想在每个选项卡中使用SplitViewController,但SplitViewController的文档说它需要是根视图控制器。因此,记住所有这些,请理解我试图并排放置两个导航控制器,并且(大部分)复制SplitViewController的行为/布局 除了视图的布局之外,其他一切都很好。当应用程序在纵向模式下启动时,当设备方向发生变

我正在开发一个通用的应用程序,我正在尝试在iPhone和iPad版本之间尽可能多地共享代码。我需要使用TabBarController作为我的根视图控制器,虽然我想在每个选项卡中使用SplitViewController,但SplitViewController的文档说它需要是根视图控制器。因此,记住所有这些,请理解我试图并排放置两个导航控制器,并且(大部分)复制SplitViewController的行为/布局

除了视图的布局之外,其他一切都很好。当应用程序在纵向模式下启动时,当设备方向发生变化时,所有功能都正常工作并正确调整大小/位置

如果应用程序以UIDeviceOrientationGrait以外的任何方向启动,则视图将在导航控制器上方显示20点间距/边距。我尝试在运行时调整帧,但没有完美的结果。将框架的origin.y调整为-20并将高度增加20会使视图与其父视图的顶部齐平,但在底部会留下20点的间隙


UINavigationController通常显示为全屏控制器,这意味着(当显示为窗口的根视图控制器时)其视图的顶部位于状态栏下。然后,当状态栏可见时,它会手动定位其导航栏和内容视图,使其不在状态栏下方。不幸的是,当它被其他视图控制器定位时,它并没有真正正确地处理事情,它(有时)假设它需要离开20px的间隙,而不检查它的视图是否实际位于状态栏下


解决方案是将UINavigationController上的wantsFullScreenLayout设置为NO,这样它甚至不会试图在状态栏上留下该间隙。

我可以按如下方式使用暴力。在
viewDidLoad
loadView
中:

if (self.navigationController.navigationBar.frame.origin.y > 0.0) {
    self.navigationController.navigationBar.frame = CGRectOffset(self.navigationController.navigationBar.frame, 0.0, -20.0);
}
并在视图中显示:

if (self.view.superview.frame.origin.y > 44.0) {
    UIView *container = self.view.superview;
    container.frame = CGRectMake(container.frame.origin.x, container.frame.origin.y - 20.0, container.frame.size.width, container.frame.size.height + 20.0);
}
这很难看,但似乎管用

正确的答案是:

CGRect r = [[_navController view] frame];
r.origin = CGPointMake(0.0f, -20.0f);
[[_navController view] setFrame:r];

不确定它是否会有帮助,但我在过去也遇到过类似的问题,并且在将UINavigationController视图添加到其superview时,通过将其框架设置为CGRectZero能够解决这一问题


在布局子视图中,我当然会更新UINavigationController视图的框架。

将视图控制器添加到选项卡栏时,这是一个常见问题

来自苹果的文档():

与大多数其他控制器支持全屏布局的方式不同,选项卡栏控制器支持全屏布局。如果希望自定义视图控制器的视图位于状态栏或导航栏(如果存在)的下方,则仍可以将其WantFullScreenLayout属性设置为“是”。但是,将此属性设置为“是”不会导致视图在选项卡栏视图的下方。“选项卡栏”控制器始终调整视图的大小,以防止视图在选项卡栏的下方覆盖

用代码的话来说,您应该执行以下操作:

UINavigationController *myNavController = [[UINavigationView alloc] init];
myNavController.wantsFullScreenLayout = YES;

//...

NSArray* controllers = [NSArray arrayWithObjects:myNavController, nil];
myTabBarController.viewControllers = controllers;
但是,如果您遇到这样的问题,即当以非
UIInterfaceOrientationGrait
的方向打开应用程序时,
myNavController
的视图将屏幕上方移动20像素,则您将动态设置控制器的
wantsFullScreenLayout
属性(而不是上述解决方案),具体取决于初始方向。 我使用导航控制器实现中定义的静态变量执行此操作:

static UIInterfaceOrientation _initialOrientation = -1;
之后,需要重载
viewdide:
方法并适当设置变量:

- (void)viewDidAppear:(BOOL)animated
{
  if (_initialOrientation == -1)
    _initialOrientation = [[UIApplication sharedApplication] statusBarOrientation];
  self.wantsFullScreenLayout = (_initialOrientation != UIInterfaceOrientationPortrait);

  [super viewDidAppear:animated];
}

希望这有帮助。

我在我的应用程序中解决了这个问题,在添加导航控制器视图后隐藏导航栏,然后显示导航栏。例如

[parentView addSubview:navController.view];
[navController setNavigationBarHidden:YES];
[navController setNavigationBarHidden:NO];

在状态栏和它下面的视图之间有一个类似的不必要的间隙问题,通过在interface builder中转到
自动调整大小
,并将有问题的视图设置为粘贴到其父视图的顶部,解决了这个问题。

奇怪的是,在iOS 6中对我有帮助的是将UINavigationController和实施此方法:

- (BOOL)wantsFullScreenLayout {
    return NO;
}

在我的故事板中取消选中“想要全屏”并没有起到作用,所以我不知道有什么不同。这肯定会在未来的iOS版本中出现。但现在,我接受它。

在导航控制器中显示的我的视图中,我将此代码放在了视图中

这段代码可能并不适用于所有应用程序,但它解决了我花了几个小时研究的问题

    // START OF BUG FIX FOR iOS
if (self.navigationController.navigationBar.frame.origin.y ==20) {
    // Move the navigation Bar up
    [self.navigationController.navigationBar setFrame:CGRectMake(0, 0, self.navigationController.navigationBar.frame.size.width, self.navigationController.navigationBar.frame.size.height)];
    // move up the table view
     [self.view setFrame:CGRectMake(0, -20, self.view.frame.size.width, self.view.frame.size.height+20)];
}
// END OF BUG FIX for IOS6

要解决此问题,只需选中故事板上的“想要全屏显示”框

出现此问题的原因是
ParentViewController
正在显示导航栏

正如苹果的文档所说:


如果您的应用程序显示状态栏,视图将缩小,使其不会位于状态栏下方。毕竟,如果状态栏不透明,则无法查看或与其下方的内容交互。但是,如果您的应用程序显示半透明状态栏,则您可以正确设置视图控制器的WantFullScreenLayout的值ty为“是”以允许您的视图全屏显示。状态栏绘制在视图顶部。

在viewDidLoad上向我的ViewController添加UITableView时,我遇到了相同的问题。我没有从self.view中抓取帧,而是从主窗口中获取该帧,使其看起来像这样

UIWindow *keyWindow = [[[UIApplication sharedApplication] delegate] window];
self.uiTable = [[UITableView alloc] initWithFrame:[keyWindow frame] style:UITableViewStylePlain];

为什么不在每次旋转时将框架调整为
self.view.frame.size.height
?@sudo-是的,我已经这样做了,这很有帮助…但只有在设备旋转的情况下!如果应用程序以除纵向以外的任何方向启动(按下按钮),看起来像是最后一个屏幕截图。我没有做任何调整。我试图消除这个差距。他们尝试将其设置为
[[UIScreen mainScreen]界限].size.height
?围绕这个主题有很多问题,没有合适的答案