iOS 7 | 导航栏/工具栏按钮与状态栏非常接近

42

当我将导航栏或工具栏(storyboard)拖到我的视图控制器时,出现了问题。

UINavigationBar:

UINavigationBar

如上图所示,右侧按钮几乎重叠在状态栏上。

UIToolbar也有同样的问题:

UIToolbar

这些视图控制器旨在用作模态视图,这就是我不使用UINavigationController的原因。

在另一个部分中,我使用UINavigationController,其显示效果与我预期相同:

UINavigationController

如何将UINavigationBar / UIToolbar拖到视图控制器中而不重叠状态栏?


你能准确地说明你是如何解决这个问题的吗?我在正确答案下面尝试了评论但它们没有帮助。我在Storyboard中拖入的uitoolbar也出现了同样的问题。 - AJ112
嗨@AJ112。你在使用自动布局吗?如果没有,请尝试将UIToolbar的固定点设置为左上角。然后,将代码放在下面的注释中(框架代码)。它应该可以工作。 - Axort
是的,我正在使用自动布局。 工具栏已经设置为固定点到左上角,但它没有起作用。 这是我的问题:https://dev59.com/iHfZa4cB1Zd3GeqPNhwy - AJ112
请确认一下,您的工具栏是否在(0,20)的位置?您的UIViewController是否已经实现了UIToolbarDelegate?如果是这样的话...您是否已经在viewDidLoad中将代理设置为IBOutlet UIToolbar?您的视图控制器是否已经实现了UIToolbarDelegate(positionForBar:)方法? - Axort
请查看以下链接:https://dev59.com/lWMl5IYBdhLWcg3wDjOg#18753695 - DogCoffee
截至2019年,您只需要将顶部布局约束设置为0(顶部)。否则,您最终会得到一个导航栏以某种负面方式定位的结果。 - Tofu Warrior
6个回答

48

1
嗨!谢谢。我尝试了你建议的方法,但它没有起作用。这是我的做法:.h -> @property (weak, nonatomic) IBOutlet UIToolbar *toolbar; AND UIViewController<UIToolbarDelegate> || 然后在 .m 的 viewDidLoad 中 -> [this.toolbar setDelegate:self]; 然后我添加到 .m 中 -> #pragma mark UIToolbarDelegate - -(UIBarPosition)positionForBar:(id<UIBarPositioning>)bar { return UIBarPositionTopAttached; } || 我做错了什么吗? - Axort
3
你必须将工具栏的位置设置为(0,20),否则它将无法正常工作。在 viewDidLoad 方法中: CGRect frame = self.toolbar.frame; frame.origin.y = 20; self.toolbar.frame = frame;。如果你只针对 iOS6 和 iOS7,可以使用 Xcode 中的 iOS6/7 deltas 来完成这个 20pt 的移动。 - Léo Natan
非常感谢!问题在于工具栏的锚点在左侧(在角落之间),而不是在左上角,因此它无法正常工作。(我没有使用自动布局:P)。我想知道为什么故事板不会将uinavigationbar或uitoolbar放置在(0,20)作为默认位置。再次感谢! - Axort
UIBarPositionTopAttached需要通过编程设置吗,还是有IB等效的方法? - Ryan
它必须在委托方法中返回。 - Léo Natan
@Cœur 感谢您抽出时间使用更新的文档链接编辑我的答案。请在需要 ObjC 的问题中添加 ObjC 文档链接。 - Léo Natan

25

按照以下步骤进行操作:

将NavigationBar拖到您的Xib视图控制器中,将该视图控制器设置为其代理。 请注意,NavigationBar 应该位于 (0,20) 的位置。

在视图控制器中,遵循 UINavigationBarDelegate 协议。

@interface ETPViewController () <UINavigationBarDelegate>

实现这个方法

- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
    return UIBarPositionTopAttached;
}

positionForBar 告诉 NavigationBar 是否应将其背景向上扩展到状态栏


嗨,如果你使用的是工具栏而不是导航栏呢?我尝试了相同的步骤,并将<UINavigationBarDelegate>替换为<UIToolbarDelegate>,但它并不起作用。 - Juan González
6
你应该使用 UIBarPositioningDelegate 代替。 - Sam Spencer

10
请看我在这里的回答,下面是方便起见复制的内容: https://dev59.com/uGMk5IYBdhLWcg3w2RaT#18912291 我发现最简单的解决方法是将您想要呈现的视图控制器包装在一个导航控制器中,然后呈现该导航控制器。
MyViewController *vc = [MyViewController new];
UINavigationController *nav = [[UINavigationController alloc] 
    initWithRootViewController:vc];
[self presentViewController:nav animated:YES completion:NULL];

优点:

  • 无需操作框架。
  • 相同的代码可在iOS 6和iOS 7上运行。
  • 比其他解决方法更美观。

缺点:

  • 您可能希望在XIB中不包含导航栏或工具栏,并在代码中向导航栏添加UIBarButtonItems。幸运的是,这很容易实现。

5
您可以通过使用自动布局来解决此问题,如技术笔记所述(防止状态栏覆盖您的视图)。
以下是一些摘录:

向最顶部的视图添加垂直间距约束

  • 从UIToolbar控件中进行控制拖动到“顶部布局指南”
  • 在弹出窗口中,选择“垂直间距”
  • 将“垂直间距约束”常量更改为0(零)

如果在UIToolbar下有其他子视图,请将这些视图锚定到工具栏而不是顶部布局指南

这将支持iOS6和iOS7。

6
值得一提的是,顶部和底部布局指南仅在storyboard中可用,其中视图嵌入在视图控制器中。使用nib文件,这个过程更加复杂。 - Léo Natan

0

您还可以通过提供大小为620x128的图像来增加iOS版本的导航栏高度进行管理。此图像用于:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)?YES:NO) {
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"newImage.png"] forBarMetrics:UIBarMetricsDefault];
}else{
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"previousImage.png"] forBarMetrics:UIBarMetricsDefault];
}

0
我不得不放弃并将导航栏高度约束设置为64在基于xib的VC中,因为尽管状态栏存在,但是viewController.topLayoutGuide.length在viewDidLoad中为0 :-[
这意味着在iPad上的非通用应用程序中,您会浪费视图顶部的20像素(因为状态栏与iPhone模拟窗口分开)

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