ViewController中的UINavigationController,视图顶部的间隙

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

除了视图的布局外,一切正常。 当应用程序以纵向模式启动时,所有function都会在设备方向更改时正确resize/位置。

纵向

如果应用程序以UIDeviceOrientationPortrait以外的任何方向启动,则视图将在导航控制器上方显示20点的间隔/空白。 我已经尝试在运行时调整框架,没有完美的结果。 将帧的原点调整为-20,将高度增加20,可以使视图与其父母的顶部齐平,但在底部留下20点的间隙!

风景取向

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

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

奇怪的是,iOS 6中对我有什么帮助的是inheritanceUINavigationController并实现这个方法:

 - (BOOL)wantsFullScreenLayout { return NO; } 

在我的故事板中取消选中“想要全屏”并没有办法,所以我不知道有什么不同。 这肯定会在iOS的未来版本中崩溃。 但现在,我会拿它。

UINavigationController通常显示为全屏控制器,这意味着(当作为窗口的根视图控制器显示时)其视图的顶部部分被置于状态栏下。 然后,当状态栏可见时,手动将其导航栏和内容视图置于状态栏的下方。 不幸的是,它在被其他视图控制器定位时并不能正确地处理事情,它(有时)假定它需要保留20px的空白而不检查它的视图是否在状态栏下。

解决scheme是将UINavigationController上的wantsFullScreenLayout设置为NO,所以它甚至不会尝试为状态栏留下空隙。

我能够蛮横的力量如下。 在viewDidLoadloadView

 if (self.navigationController.navigationBar.frame.origin.y > 0.0) { self.navigationController.navigationBar.frame = CGRectOffset(self.navigationController.navigationBar.frame, 0.0, -20.0); } 

而在viewDidAppear:

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

这是丑陋的,但似乎工作。

要解决这个问题,只需勾选故事板上的Wants Full Screen

出现问题的原因是ParentViewController显示导航栏。

正如苹果文档所言:

如果您的应用程序显示状态栏,则视图会缩小,以使其不会覆盖状态栏。 毕竟,如果状态栏是不透明的,就没有办法看到它下面的内容。 但是,如果您的应用程序显示半透明的状态栏,则可以将视图控制器的wantsFullScreenLayout属性的值设置为YES,以允许您的视图全屏显示。 状态栏绘制在视图的顶部。

不知道是否会有任何帮助,但过去也遇到类似的问题,通过将UINavigationController视图的框架添加到其超级视图时,可以将UINavigationController视图的框架设置为CGRectZero。

在layoutSubviews中,我更新了UINavigationController视图的框架。

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

从Apple的文档( 选项卡栏控制器 – 选项卡栏和全屏布局 ):

标签栏控制器支持全屏布局,与大多数其他控制器支持的方式不同。 如果您希望其视图的状态栏或导航栏(如果存在)不足,您仍然可以将自定义视图控制器的wantsFullScreenLayout属性设置为YES。 但是,将此属性设置为YES不会导致视图与选项卡栏视图不一致。 标签栏控制器总是调整您的视图,以防止它的标签栏下面。

用代码的话说,你应该做下面的事情:

 UINavigationController *myNavController = [[UINavigationView alloc] init]; myNavController.wantsFullScreenLayout = YES; //... NSArray* controllers = [NSArray arrayWithObjects:myNavController, nil]; myTabBarController.viewControllers = controllers; 

但是 ,如果你遇到了以myNavController之外的方向打开应用程序的问题,那么你的myNavController的视图将屏幕上的20个pix移到顶部,那么你将会dynamic地设置controller的wantsFullScreenLayout属性(而不是上面的解决scheme),取决于最初的方向。 我使用导航控制器实现中定义的静态variables来完成此操作:

 static UIInterfaceOrientation _initialOrientation = -1; 

之后,您需要重载viewDidAppear:方法并适当地设置variables:

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

希望这可以帮助。

当我在viewDidLoad的ViewController中添加一个UITableView时遇到了同样的问题。 我不是从self.view中抓取框架,而是从主窗口中获得它,看起来像这样

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

在状态栏和正below的视图之间有一个类似的问题,通过在界面生成器中进行自动设置并将视图设置为其父视图的顶部来解决这个问题。

在我看来,这是显示在navigationcontroller内我把这个代码里面的viewDidAppear

这个代码可能不是完美的每一个应用程序,但它解决了我花了几个小时踢在我的问题..

  // 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 

正确的答案是:

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