隐藏UIStatusBar / 移动UINavigationBar

3
我有一个基于导航的应用程序,用户可以隐藏状态栏。这是在默认设置中记住的。
它大部分正常工作,但有一个例外情况:如果应用程序在状态栏可见时被加载(从头开始,而不是返回到主屏幕后),当将其切换为不可见时,导航栏不会上移以填充屏幕。在那之后切换设置可以正确地将导航栏上下移动,但仍然存在额外的状态栏大小间隙,即导航栏和屏幕顶部或状态栏之间。如果我返回到主屏幕并重新进入应用程序,则会自动更正。因此,我认为在返回应用程序时调用了一些针对uinavigationcontroller的方法,我需要在切换状态栏后调用它?
我已经尝试了(我想)所有的wantsfullscreenlayout属性组合,在下面的方法中进行了设置,但没有任何效果,所以我最终在nib中将其(在navigationcontroller上)设置为NO。
以下是切换状态栏的代码。这在我的应用程序委托中,该委托具有按照模板应用程序设置的navigationcontroller和window。
if ([UIApplication sharedApplication].statusBarHidden != hideStatusBar)
{
    [[UIApplication sharedApplication] setStatusBarHidden:hideStatusBar withAnimation:UIStatusBarAnimationSlide];
    [UIView animateWithDuration:0.25 animations:^{
        window.frame = [[UIScreen mainScreen] applicationFrame];
    }];
}
else
{
    window.frame = [[UIScreen mainScreen] applicationFrame];
}

感谢您的帮助。
更新
通过 NSLogging,似乎问题在于 UINavigationBar 的框架。所以我添加了以下代码,它可以工作和动画,但我不是很满意!我觉得这不可能是“正确”的方法。在大多数情况下,额外的代码并没有起到任何作用,因为框架已经在 (0,0) 处,但在某些情况下,它是不正确的,这样做可以得到正确的结果。
[navigationController.view setNeedsLayout];
CGRect navBarFrame;
UINavigationBar *navBar = nil;
for (UIView *subView in navigationController.view.subviews)
{
    if ([subView isMemberOfClass:[UINavigationBar class]])
    {
        navBar = (UINavigationBar *)subView;
        navBarFrame = navBar.frame;
        navBarFrame.origin = CGPointMake(0,0);
        break;
    }
}

if ([UIApplication sharedApplication].statusBarHidden != hideStatusBar)
{
    [[UIApplication sharedApplication] setStatusBarHidden:hideStatusBar withAnimation:UIStatusBarAnimationSlide];
    [UIView animateWithDuration:0.25 animations:^{
        window.frame = [[UIScreen mainScreen] applicationFrame];
        navBar.frame = navBarFrame;
    }];
}
else
{
    window.frame = [[UIScreen mainScreen] applicationFrame];
}

尝试调用 [self.view setNeedsDisplay]。 - Bushra Shahid
没有self.view,这个在应用程序委托中。你是指navigationController.view吗? - jrturton
是的,无论当前视图是什么。 - Bushra Shahid
如果您正在使用IB添加导航栏,可以尝试使用出现的箭头将其附加到窗口顶部。这只是一个随机建议。 - Bushra Shahid
4个回答

1
窗口总是低于状态栏,所以您不应尝试重新调整它的大小。 相反,将窗口根视图控制器的视图大小调整为[[UIScreen mainScreen] applicationFrame]

窗口没有设置rootviewcontroller出口,这应该是导航控制器吗? - jrturton
是的。抱歉,我应该更清楚地表达。在applicationDidFinishLaunching:withOptions:中将您添加为窗口子视图的任何视图调整大小(几乎肯定是导航控制器的视图)。rootViewController属性是您可以设置它的新方法,但大多数应用程序仍然只将视图控制器的视图作为窗口的子视图添加。 - cduhn
那会给出与之前相同的结果。 - jrturton
哦,没错。我忘了UINavigationController在状态栏隐藏时不会自动响应。一个可行的hack是将导航控制器的视图从窗口中移除,然后立即重新添加它。我会尝试一下看是否能找到更优雅的解决方案。 - cduhn
1
我发现你不需要删除并重新添加导航控制器。你可以使用 [self.navigationController setNavigationBarHidden:YES animated:NO]; [self.navigationController setNavigationBarHidden:NO animated:NO]; 来切换导航栏的可见性。这会强制导航控制器调整导航栏布局,但它不会有良好的动画效果。所以你的 hack 可能更好。 - cduhn

1
问题出在UINavigationBar的框架上。因此,我添加了以下代码,它可以工作和动画,但我对此并不满意!我觉得这不可能是“正确”的方法。在大多数情况下,额外的代码什么也不做,因为框架已经在(0,0)处,但在一个不正确的情况下,这会给出正确的结果。
[navigationController.view setNeedsLayout];
CGRect navBarFrame;
UINavigationBar *navBar = nil;
for (UIView *subView in navigationController.view.subviews)
{
    if ([subView isMemberOfClass:[UINavigationBar class]])
    {
    navBar = (UINavigationBar *)subView;
    navBarFrame = navBar.frame;
    navBarFrame.origin = CGPointMake(0,0);
    break;
    }
}

if ([UIApplication sharedApplication].statusBarHidden != hideStatusBar)
{
    [[UIApplication sharedApplication] setStatusBarHidden:hideStatusBar withAnimation:UIStatusBarAnimationSlide];
    [UIView animateWithDuration:0.25 animations:^{
    window.frame = [[UIScreen mainScreen] applicationFrame];
    navBar.frame = navBarFrame;
    }];
}
else
{
    window.frame = [[UIScreen mainScreen] applicationFrame];
}

0
据我所知,如果您隐藏状态栏,您的视图会自动占用新空间,您不必手动更改窗口框架。如果您尝试这样做,会发生什么?
if ([UIApplication sharedApplication].statusBarHidden != hideStatusBar)
{
    [[UIApplication sharedApplication] setStatusBarHidden:hideStatusBar withAnimation:UIStatusBarAnimationSlide];
}

1
这样就可以保留导航栏的位置 - 这也是我最初开始尝试隐藏状态栏并在导航控制器上设置wantsfullscreenlayout属性的地方。 - jrturton

0

这是解决我的方法

只是一个视图:

[self.view setFrame: [self.view bounds]];

一个包含滚动视图的视图
[self.view setFrame: [self.view bounds]];
[self.theScroller setFrame: [self.view bounds]];

"theScroller" 是我滚动视图的名称。


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