有没有办法在不使用UINavigationController的情况下更改Storyboard中UINavigationBar的高度?

时间:2013-12-07 08:01:39

标签: ios objective-c cocoa-touch uinavigationcontroller uinavigationbar

我想在我的一个视图中使用自定义UINavigationBar,这不是任何UINavigationController层次结构的一部分。当我将UINavigationBar拖到Storyboard中时,它显示如下:

UINavigationBar

此栏为44px,如果状态栏不共享此空间就足够了。因为iOS7允许我们使用整个屏幕,包括状态栏的空间,UINavigationBar应该是64px高,而不是44px。

如果我将视图连接到UINavigationController的层次结构,那么它显示正确:

UINavigationController

我在某处读到如果 UINavigationBar将属性barPosition:设置为UIBarPositionTopAttached,那么该栏将为64px。但是,这是readonly - 属性。

我的搜索结果只显示了我认为是“解决方法”的问题。通过在此UINavigationController之前添加无用的UIViewController,我可以假装有一个层次结构,它会自动添加UINavigationBar 64px。

是否真的没有办法覆盖64px的'流氓'(没有导航控制器的帮助)UINavigationBar? 如果是这种情况,是否有任何正当理由?

(我不是说默认情况下UINavigationBar应该是64px,但在检查器中应该有一个选项)

(我也看到人们用程序化的方式来解决这个问题。即使这些答案有效,我仍然必须设计故事板,考虑到这一点(差距)。我想要什么要知道是否可以在故​​事板中设置它,或者更确切地说,为什么不允许它?)

11 个答案:

答案 0 :(得分:45)

您可以将属性barPosition另设为UIBarPositionTopAttached

  1. 将代理人添加到您的UINavigationBar。
  2. 在委托类中实施-positionForBar:

    - (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar
    {
        return UIBarPositionTopAttached;
    }
    
  3. 您的导航栏顶部也必须固定在顶部布局指南中。

答案 1 :(得分:25)

您可以通过编程方式更改导航栏高度:

[navBar setFrame:CGRectMake(0, 0, 320, 64)];

编辑:正如我在评论中写的那样,您可能必须在viewDidLayoutSubviews中放置这一行以规避自动布局。

答案 2 :(得分:10)

您可以使用&#39;用户定义的运行时属性&#39;将其设置为附加到视图的顶部。在身份检查员&#39;在Interface Builder中。设置barPosition属性。

enter image description here

以下是barPosition媒体资源的文档:https://developer.apple.com/library/ios/documentation/uikit/reference/UIBarPositioning_Protocol/Reference/Reference.html

答案 3 :(得分:8)

有一种方法可以在不使用UINavigationController或以编程方式设置它的情况下完成此操作。只需在导航栏上将高度约束设置为您想要的任何值,在此实例中为64。

您可以通过编程方式完成相同的操作:

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:navigationBar attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1 constant:64.0f]];

编辑:

正如@ n​​erdist-colony指出的那样,在使用Autolayout时,始终将translatesAutoresizingMaskIntoConstraints设置为NO,否则可能会出现约束冲突。

答案 4 :(得分:3)

我也使用独立的UINavigationBar,我遇到了同样的问题,我发现有两种方法可以正确解决这个问题。

我使用约束和父UIView修复它。我在故事板中将此UIView设置为具有{0,0,320,64}帧的UINavigationBar的父视图。您可以添加约束或一组约束,强制UINavigationBar具有所需的大小。 鉴于您的父UIView在故事板中具有正确的框架,您可以像往常一样在故事板中布置其他视图。

现在,如果禁用autolayout,您可以按照Lindsey的答案中的描述以编程方式更改条形高度。 -(void)viewDidLayoutSubviews似乎是一个很好的选择。

答案 5 :(得分:2)

如果您使用Autolayout,则可以将UINavigationBar约束的高度设置为64或更多事件。

答案 6 :(得分:1)

@startupThekid:

如果您尝试更改由UINavigationController管理的UINavigationBar的自动调整掩码,iOS将生成异常。

但是,您发布的目标C代码的Swift等价物是:

var navBar = self.navigationController!.navigationBar 
viewDidAppear ()中的

navBar.setTranslatesAutoresizingMaskIntoConstraints = false

无论您何时需要设置约束:

var navBarHeightConstraint = 
      NSLayoutConstraint(item: navBar, attribute: .Height,
            relatedBy: .Equal, toItem: nil, 
            attribute: .Height, multiplier: 1, constant: height)

self.view.addConstraint(navBarHeightConstraint)

之后您应该能够根据需要修改约束的常量属性以更改导航栏高度,例如更改设备方向

答案 7 :(得分:1)

我写了一篇博文,详细介绍了如何通过最少的代码干预来完成这项工作。您的栏会在故事板中显示间隙,但它可以在设备上正常工作。简而言之,步骤是:

1)将导航栏添加到故事板中的视图控制器。

2)在故事板中设置导航栏的约束:
    - 导航栏。顶部=顶部布局指南。底部
    - 导航栏。领导= Superview.Leading
    - 导航Bar.Trailing = Superview.Trailing

3)将storyboard的导航栏作为@IBOutlet连接到其视图控制器。

4)在视图控制器的类中,将UINavigationBarDelegate协议添加到类声明中。

5)在视图控制器的viewDidLoad方法中,将导航栏的委托设置为self。

6)在视图控制器中,添加条形定位委托的positionForBar方法。返回表示TopAttached的UIBarPosition。 (注意:UINavigationBarDelegate从UIBarPositioningDelegate继承此方法。)

GIF图片的完整帖子在这里:
Easily use a Navigation Bar without a corresponding Navigation Controller

这些步骤适用于Swift 2.1 / Xcode 7.2

答案 8 :(得分:1)

在使用主故事板的Swift 3中,您可以使用约束来更改高度并使其工作。这是我发现易于实现的方式。

Creating the constraints.

What it looks like in the end.

答案 9 :(得分:0)

我在同一条船上遇到问题,但现在我已经修好了。我正在尝试做正确的事情以避免明确地设置框架,这对于面向未来并且容易支持不同的设备尺寸是可取的。就我而言,我想在导航栏下面看一个webview。

我将视图控制器设置为UINavigationBarDelegate并实施positionForBar:以返回UIBarPositionTopAttached,例如user3269713's answer。似乎另一个技巧是使用自动布局将栏定位在topLayoutGuide下方。

这个创建导航栏后我在viewDidLoad中使用的代码。 webview以编程方式,我仍然看到酒吧卡在高44,但不能立即看到原因:

    [navigationBar sizeToFit];
    navigationBar.delegate = self;
    [self.view addSubview:navigationBar];
    [self.view addSubview:webView];
    id guide = self.topLayoutGuide;
    NSDictionary *viewNamesDict = NSDictionaryOfVariableBindings(webView, navigationBar, guide);
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[webView]|" options:0 metrics:nil views:viewNamesDict]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[guide][navigationBar][webView]|" options:0 metrics:nil views:viewNamesDict]];

但是我做了一些更多的思考并玩弄了自动布局,事实证明这就是我的问题的原因。我试图依靠导航栏自动调整掩码的翻译约束,但事实证明我需要明确定义它们。这是我的新viewDidLoad代码:

    [navigationBar sizeToFit];
    navigationBar.delegate = self;
    navigationBar.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:navigationBar];
    [self.view addSubview:webView];
    id guide = self.topLayoutGuide;
    NSDictionary *viewNamesDict = NSDictionaryOfVariableBindings(webView, navigationBar, guide);
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[navigationBar]|" options:0 metrics:nil views:viewNamesDict]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[webView]|" options:0 metrics:nil views:viewNamesDict]];
    NSString *verticalLayoutVisualExpression = [NSString stringWithFormat:@"V:|[guide][navigationBar(%f)][webView]|", navigationBar.frame.size.height];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:verticalLayoutVisualExpression options:0 metrics:nil views:viewNamesDict]];

是的,正如我所希望的那样,当转向横向并隐藏状态栏时,这会自动移动横杆。

(我衷心推荐一个像砌体一样的自动布局助手,它使布局代码更加简洁,而Masonry为一个人负责为你关掉translatesAutoresizingMaskIntoConstraints

答案 10 :(得分:0)

我知道这是一种非常黑客的做法,但对我来说这很有用。我有一个NavigationViewController,我希望以模式方式加载一个ViewController,其顶部有一个UINavigationBar,带有Done和Cancel按钮。这就是它的样子:enter image description here

正如您所看到的,顶部有一条白色条带,我想要与UINavigationBar颜色相同。我没有以编程方式更改UINavigationBar的高度,而是创建了一个新视图并将其背景颜色设置为等于UINavigationBar的背景颜色(HEX = F8F8F8,RGBA = 248,248,248,1.0)。再一次,我知道这是超级hacky,但它为我完成了工作。这就是现在的样子

enter image description here