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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5183834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 20:22:55  来源:igfitidea点击:

UINavigationController within ViewController, gap at top of view

iphonexcodeipadiosinterface-builder

提问by E-Madd

I'm working on a universal app, and I'm trying to share as much code as possible between the iPhone and iPad versions. I need to use a TabBarController as my root view controller and though I'd like to use a SplitViewController in each of the tabs, SplitViewController's docs say it needs to be the root view controller. So, with all of that in mind - understand that I'm attempting to place two navigation controllers side-by-side and (mostly) replicate the behavior/layout of a SplitViewController.

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

Everything works just fine, except for the layout of the views. When the app is started in portrait mode, everything functions and resizes/positions correctly when the device orientation changes.

一切正常,除了视图的布局。当应用程序以纵向模式启动时,当设备方向发生变化时,一切都会正常运行并正确调整大小/位置。

portrait orientation

纵向

If the app is started in any orientation other than UIDeviceOrientationPortrait, the view displays with a 20 point gap/margin above the navigation controller. I've tried adjusting the frame at runtime with no perfect result. Adjusting the origin.y of the frame to -20 and increasing the height by 20 brings the view flush with the top of it's parent, but it leaves a 20 point gap at the bottom!

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

landscape orientation

横向

回答by kevin

I solved this in my app by hiding then showing the navigation bar after adding the navigation controllers view. eg.

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

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

回答by Brent Royal-Gordon

Oddly enough, what's helping for me in iOS 6 is subclassing UINavigationController and implementing this method:

奇怪的是,在 iOS 6 中对我有帮助的是继承 UINavigationController 并实现这个方法:

- (BOOL)wantsFullScreenLayout {
    return NO;
}

Unchecking "Wants Full Screen" in my storyboard didn't do the trick, so I don't know what's different. This could certainly break in a future version of iOS. But for now, I'll take it.

在我的故事板中取消选中“想要全屏”并没有解决问题,所以我不知道有什么不同。这肯定会在未来版本的 iOS 中被打破。但现在,我会接受它。

回答by ant_one

To fix this problem just check the box Wants Full Screenon the storyboard.

要解决此问题,只需选中Wants Full Screen故事板上的框即可。

The problem appears because the ParentViewControlleris showing the navigation bar.

出现问题ParentViewController是因为正在显示导航栏。

As apple documentation said :

正如苹果文档所说:

If your app displays the status bar, the view shrinks so that it does not underlap the status bar. After all, if the status bar is opaque, there is no way to see or interact with the content lying underneath it. However, if your app displays a translucent status bar, you can set the value of your view controller's wantsFullScreenLayout property to YES to allow your view to be displayed full screen. The status bar is drawn over the top of the view.

如果您的应用程序显示状态栏,则视图会缩小,以免与状态栏重叠。毕竟,如果状态栏是不透明的,则无法查看其下方的内容或与其进行交互。但是,如果您的应用程序显示半透明状态栏,您可以将视图控制器的 WantsFullScreenLayout 属性的值设置为 YES 以允许您的视图全屏显示。状态栏绘制在视图的顶部。

回答by Anomie

UINavigationController is normally displayed as a full-screen controller, which means that (when displayed as the root view controller of the window) the top part of its view is placed under the status bar. It then manually positions its navigation bar and content view to notunderlap the status bar when the status bar is visible. Unfortunately, it doesn't really handle things correctly when it is being positioned by some other view controller, it (sometimes) assumes it needs to leave that 20px gap without checking whether its view actually isunder the status bar.

UINavigationController 通常显示为全屏控制器,这意味着(当显示为窗口的根视图控制器时)其视图的顶部位于状态栏下方。然后,当状态栏可见时,它手动定位其导航栏和内容视图,使其与状态栏重叠。不幸的是,它并没有真正正确地处理事情,当它被定位通过一些其他视图控制器,它(有时)假设它需要留下20px的差距,不检查其观点是否真的状态栏下。

The solution is to set wantsFullScreenLayouton the UINavigationController to NO, so it won't even attempt to leave that gap for the status bar.

解决方案是wantsFullScreenLayout将 UINavigationController设置为 NO,因此它甚至不会尝试为状态栏留下该间隙。

回答by Frank Schmitt

I was able to brute force as follows. In viewDidLoador loadView:

我能够蛮力如下。在viewDidLoadloadView

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

And in viewDidAppear:

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

It's ugly, but it seems to work.

这很丑陋,但似乎有效。

回答by Yannick Compernol

Not sure whether it'll be of any help, but I've had similar issues in the past and have been able to resolve this by setting the frame of the UINavigationController view to CGRectZero when adding it to its superview.

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

In layoutSubviews I update the frame of the UINavigationController view of course.

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

回答by Micha? Orlik

This is a common issue when adding view controllers to a tab bar.

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

From Apple's documentation (Tab Bar Controllers - Tab Bars and Full-Screen Layout):

来自 Apple 的文档(Tab Bar Controllers - Tab Bars and Full-Screen Layout):

Tab bar controllers support full-screen layout differently from the way most other controllers support it. You can still set the wantsFullScreenLayout property of your custom view controller to YES if you want its view to underlap the status bar or a navigation bar (if present). However, setting this property to YES does not cause the view to underlap the tab bar view. The tab bar controller always resizes your view to prevent it from underlapping the tab bar.

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

In words of code, you should do the following:

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

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

//...

NSArray* controllers = [NSArray arrayWithObjects:myNavController, nil];
myTabBarController.viewControllers = controllers;

If, however, you run into the problem that when opening application in orientation other than UIInterfaceOrientationPortraityour myNavController's view moves 20 pix off the screen to the top, then you will have set controller's wantsFullScreenLayoutproperty dynamically (instead of the above solution), depending on the initial orientation. I do it using a static variable defined in your navigation controller implementation:

但是,如果您遇到的问题是,在以不同于UIInterfaceOrientationPortraitmyNavController的视图的方向打开应用程序时,将屏幕移出 20 像素到顶部,那么您将wantsFullScreenLayout动态设置控制器的属性(而不是上述解决方案),具体取决于初始方向。我使用在您的导航控制器实现中定义的静态变量来做到这一点:

static UIInterfaceOrientation _initialOrientation = -1;

After that you need to overload the viewDidAppear:method and set the variable appropriately:

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

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

  [super viewDidAppear:animated];
}

Hope this helps.

希望这可以帮助。

回答by NoahSteam

I ran into the same issue when adding a UITableView to my ViewController on viewDidLoad. Instead of grabbing the frame from self.view, I got it form the main window so that it looks like this

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

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

回答by J3RM

In my view that is displayed inside the navigationcontroller I put this code inside the viewDidAppear

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

This code may not be perfect for every application but it fixed my issue I spent several hours kicking at..

这段代码可能并不适合每个应用程序,但它解决了我花了几个小时解决的问题。

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

回答by bertz

had a similar problem with the unwanted gap between the status bar and the view directly belowit, solved it by going to autosizingin interface builder and setting the view in question to stick to the top of its parent view.

有一个类似的问题,即状态栏和视图之间不需要的间隙直接below它,通过进入autosizing界面构建器并将有问题的视图设置为坚持其父视图的顶部来解决它。