导航栏自适应大小

12

在我的应用程序中,我有一个UINavigationController。不幸的是,当我旋转设备并且界面方向改变时,UINavigationBar并没有改变其高度。在其他iPhone应用程序(例如Contacts.app)中,在横向模式下,导航栏会略微缩短。这一定是内置的,因为如果您从XCode菜单中获取导航示例应用程序并添加接口方向,则会正确更改导航栏的高度。

如何使导航栏像我看到的所有其他iPhone应用程序一样调整大小?

8个回答

19

我已经进行了一些测试,虽然我不喜欢这种方法,但这很容易实现。

尽管我寻找了可能有效的私有方法,但我找不到。我发现的只有:

@property BOOL forceFullHeightInLandscape;

- (BOOL)isMinibar;

-isMinibar 没有 setter 方法,因此我们不能设置它。我猜它的返回值是基于它的高度。同时,forceFullHeightInLandscape 被设置为 NO,但是它仍然没有调整它的高度。

当将 autoresizingMask 更改为包括 UIViewAutoresizingFlexibleHeight 时,视图的大小确实调整为更小了,但现在它太小了。不过,-isMinibar 突然返回了 YES。所以这让我想到让视图自己调整大小,把它调整到正确的高度。

因此,这是一个即使没有使用私有API方法也可以工作的方法:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [self.navigationBar performSelector:@selector(sizeToFit) withObject:nil afterDelay:(0.5f * duration)];
}

你需要处理的一件事是,下面的视图不会根据更小的栏自动调整大小,因此栏和下方的视图之间会有一个间隙。最简单的解决方法是添加一个容器视图,就像使用 UINavigationController 一样。你可以实现以下类似的代码:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [self performSelector:@selector(resizeViewsForNavigationBar) withObject:nil afterDelay:(0.5f * duration)];
}

- (void)resizeViewsForNavigationBar {
    [self.navigationBar sizeToFit];

    // Resize containerView accordingly.
    CGRect containerViewRect = self.containerView.frame;
    containerViewRect.origin.y = CGRectGetMaxY(self.navigationBar.frame);
    containerViewRect.size.height = CGRectGetMaxY(self.view.frame) - containerViewRect.origin.y;
    self.containerView.frame = containerViewRect;
}

谢谢你的回答,我现在无法测试它,但一旦尝试过后我会回报。有趣的是,容器视图已经正确地调整大小,就好像导航栏已经变短了一样。 - ryyst
我刚试了一下,它完美地工作了!由于容器视图已经正确调整大小,所以我只需要 sizeToFit 调用。 - ryyst
太好了。不过你可能需要发送一个错误报告,因为你正在使用默认的 UINavigationController,它应该可以正常工作。容器已经正确地调整大小,所以 UINavigationBar 也应该如此。 - Joost
略微变动这个修复方案可能会对今天的人们有所帮助(在iOS10中仍然会发生这种情况)。如果您不想折叠到状态栏中,但仍需要调整宽度,则可以使用此方法。self.navigationBar.frame = CGRectMake(self.navigationBar.frame.origin.x, self.navigationBar.frame.origin.y, [self.navigationBar sizeThatFits:self.navigationBar.bounds.size].width, self.navigationBar.frame.size.height); - Gabe

2
感谢Joost的帮助,我已经添加了。
@property BOOL forceFullHeightInLandscape;

将以下代码添加到我的自定义UINavigationBar类中,并设置:

-(id)initWithFrame:(CGRect)frame{
forceFullHeightInLandscape = YES;
非常有效

您还可以在UINavigationBar类别中覆盖此设置:- (BOOL)forceFullHeightInLandscape { return YES; } - Sandy Chapman

2
与Joost的答案类似,但是将方法放在willAnimateRotationToInterfaceOrientation中比将其放在willRotateToInterfaceOrientation中具有更好的动画效果。(没有动画延迟)
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [self.navigationBar sizeToFit];
}

2
我认为您想要的行为只在导航控制器(代表栏(导航或工具栏))添加到应用程序委托中的窗口或由选项卡栏等呈现时发生。
您可以通过IB或代码添加导航栏,但这并不意味着您拥有导航控制器。我的建议是创建一个导航控制器,并使用您正在处理的视图控制器对其进行初始化。可能当视图旋转时,导航栏会收缩一点,以您喜欢的方式。
希望能有所帮助。

这正是我所做的,但不,它不起作用。还是谢谢你的回答! - ryyst

1
我也遇到了这个错误,虽然原因可能不同,但我想在这里发布它以帮助其他犯错的人。
如果您覆盖任何willRotateToInterface方法,请记得调用super。
我忘了这一点,但一旦我看到了接受的答案,就想起来了。

0

我刚刚在Interface Builder和Xcode中尝试了一些东西,只要您将UINavigationBarController用作RootViewController,它就像描述的那样工作-变小。您是否在控制器本身或控制器加载方式的某些部分进行了任何更改?特别是涉及事件触发方面的更改?我曾经有过一些关于UITabBarController破坏适当消息传递并产生一些“有趣”的视图副作用的不良经历。这只是一个尝试和猜测。


好的,我确实也在使用UITabBarController。除此之外,我使用代码创建所有内容,没有使用Interface Builder。 - ryyst
啊,好的,看到已经有答案了,我很好奇如果你只是在程序中使用UITabBar会怎样。那么它还是不能工作吗?我想它应该都包含在RootViewController中。也许这不是一个真正的错误,而是与两个控制器不正常工作有关。如果你试图在Interface Builder中这样做,它不会起作用,不允许将NavigationBarController与UITabBarController混合使用。 - mic

0

你确定导航栏高度缩小不是内置的吗? - ryyst
它必须是内置的,因为如果您从XCode菜单中获取导航示例应用程序并向其添加界面方向,则确实会正确更改导航栏的高度。 - ryyst

-1
(void)viewWillLayoutSubviews {
      self.navigationItem.titleView.bounds = self.navigationController.navigationBar.bounds;
}

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