将UINavigationController作为UIView的子视图添加

13

我想在UINavigationController上方显示一个UILabel。问题在于,如果我将UILabel作为UIWindow的子视图添加,它不会自动旋转,因为它不是UIViewController的子视图(UIViewController会自动处理旋转期间更新子视图的情况)。

我最初使用的层次结构如下:

  • UIWindow
    • UILabel
    • UINavigationController

所以我想可以采用以下层次结构:

  • UIWindow
    • UIViewController
      • UIView
        • UILabel
        • UINavigationController

这样可以在UINavigationController的导航栏之上显示标签,同时由于其是UIViewController的子视图,因此也会自动旋转。

然而,当我尝试将UINavigationController添加为视图的子视图时,出现了问题:

[myViewController.view addSubview:myNavigationController.view];

出现了一个向下偏移20像素的问题,我猜测这是因为它认为需要为状态栏腾出空间。但是,由于UINavigationController被放置在一个不覆盖状态栏的UIView中,所以它错误地添加了额外的20像素。换句话说,UINavigationBar的顶部位于屏幕的第40个像素标记处,而不是在20像素处。

有没有一种简单的方法来将UINavigationController及其所有元素(例如导航栏,工具栏,根视图控制器)上移20像素?或者让它知道它不应该为状态栏进行补偿?

如果没有,我想我需要使用上面提到的第一个层次结构,并找出如何旋转标签,使它与导航栏的旋转一致。在哪里可以找到更多关于如何做到这一点的信息?

注:通过“在导航栏顶部显示标签”,我的意思是它应该覆盖在导航栏的顶部...它不能简单地包裹在一个栏按钮项中并作为导航栏项目之一放置。

5个回答

18

使用这段代码似乎有效:

nav.view.frame = CGRectMake(nav.view.frame.origin.x, nav.view.frame.origin.y - 20,
                          nav.view.frame.size.width, nav.view.frame.size.height);

在将导航控制器作为子视图添加之前,我做过这件事。使用 [UIApplication sharedApplication].statusBarFrame 而不是硬编码的 20 可能也是一个好主意。

但我不确定这是否是最好的方法。


5
使用 nav.view.frame = CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height); 可以使其在iPad上也起作用,因为iPad没有+20的错误,但会出现其他宽度和高度的问题。总体而言,这是一个非常糟糕的问题,苹果公司做得很草率。 - valexa
2
我有一个实例,如果我在iPad上的横向模式下将UINavigationController视图作为子视图加载,我会遇到20像素的错误。但只有第一次。稍后我可以重新添加到父视图中,问题就会消失。非常非常令人沮丧。 - Daniel Wood
看起来我也有同样的问题。没有什么真正告诉我导航栏在垂直方向上有20像素的偏移量。@DanielWood 我真的分享你的沮丧。如果我推送然后弹出另一个控制器,一切都没问题,但第一次...我试着玩一下。 - Vaseltior
1
我认为句子“在将导航控制器添加为子视图之前,我已经完成了这个操作。”应该以粗体、红色、下划线字体书写——对我来说,这是解决20像素问题最关键的部分。当我在将导航视图添加为子视图之前设置其框架时,问题就解决了 :) - Neo
这应该可以解决在父子视图上多次重新加载navigationView的问题。https://gist.github.com/2961401 - ArtSabintsev

2
为什么不使用App Frame而是添加一些值到origins中呢?我的意思是使用:
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];

作为一个参考框架,可以做如下操作:
nav.view.frame = CGRectMake(appFrame.origin.x, appFrame.origin.y, ...

这个对我有用。

2

如果您想要一个代表可用内容区域的框架,那么您应该使用:[[UIScreen mainScreen] applicationFrame]。当然,这将限制您的顶级视图控制器,使其只能是顶级。因此仍然有点棘手,但不那么棘手。


0

我曾经遇到过同样的问题,但最终成功解决了。

我发现我的视图控制器的视图具有正确的框架,但是视图控制器的导航栏没有(它的框架原点为(0,20))。

将以下代码插入到作为导航控制器父视图的视图控制器中:

- (void) viewDidAppear:(BOOL)animated {
    if (navigationController.navigationBar.frame.origin.y != 0) {
        [[navigationController view] removeFromSuperview];
        [[self view] addSubview:navigationController.view];
    }
}

0
Swift 5: 在UINavigationController的根视图控制器的viewDidLoad()中添加以下行。
self.edgesForExtendedLayout = [.top, .bottom]

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