iOS 7 - 状态栏重叠在视图上

109

我有一个ViewControllerUINavigationcontroller中,但导航栏是隐藏的。当我在iOS 7上运行应用程序时,状态栏显示在我的视图顶部。有没有办法避免这种情况?

我不想写任何特定于操作系统的代码。

输入图像说明

我尝试将 View controller-based status bar appearance 设置为NO,但没有解决问题。


我已经发布了我的答案,以在iOS 7中显示类似于iOS 6的状态栏。https://dev59.com/fGMl5IYBdhLWcg3wknsT#19044681 - Desert Rose
2
你需要调整y坐标和delta值来解决状态栏问题。这个链接可能会对你有帮助:https://dev59.com/IGMk5IYBdhLWcg3wxAvy。 - Ganapathy
14个回答

95

Xcode 5具有,这是专门用于解决此问题的功能。在Storyboard中,我将我的视图下移20个像素以在iOS 7上呈现正确的外观,并为了使其适用于iOS 6,我将Delta y更改为-20。

enter image description here

由于我的Storyboard没有使用自动布局,在iOS 6上正确调整视图高度的方法是设置Delta height以及Delta Y


8
你的答案是正确的,但对于4英寸的显示屏无效。如果可能的话,请更新你的答案,使其也能适用于4英寸的显示屏。先行致谢。 - user2435304
2
@AnkitMehta 我没有为4英寸的iPhone做任何特定的事情。 - aryaxt
5
对我有用。请注意,为了查看这些差异,您必须在Storyboard的“身份和类型”下取消选择“使用自动布局”。 - marsant
2
我发现除了将∆Y设置为-20之外,我还必须将∆Height设置为+20。 - Toland Hon
3
当状态栏高度发生变化时会发生什么?例如:当用户激活热点等操作时,高度为40像素... - Lukasz
显示剩余8条评论

68
如果您根本不想要任何状态栏,您需要使用这些数据更新您的plist: 为此,在plist中添加这2个设置:
<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

iOS 7希望你在设计应用时考虑到一个覆盖透明状态栏的设计。例如,查看新的iOS 7天气应用程序。


3
这实际上是唯一一个好答案,因为它以原本预期的方式从根本上修复了问题。因此需要点赞! - eleven59
5
在某些情况下,隐藏状态栏可能是合适的,但你需要非常小心。只有在视图正当地全屏时,例如媒体播放器或图像查看器,才可以这样做。 - SmileBot
1
@eleven59,您的意思是苹果公司的独裁者们打算的方式。 - JohnK
1
绝对比改变视图控制器的偏移量要好得多(这感觉非常不规范)。 - Benjamin Oman
@FahimParkar 我同意,不过我的理解是用户要求类似的东西。在某些应用程序中这是有意义的,在其他应用程序中则没有那么多意义。 - Nathan H
显示剩余5条评论

43

这是iOS 7上UIViewController的默认行为。视图会全屏显示,意味着状态栏会覆盖您视图的顶部。

如果您在UINavigationController中有一个UIViewController并且navigationBar可见,则可以在您的viewDidLoad中使用以下代码或为navigationBar设置背景图片来解决此问题。

self.edgesForExtendedLayout = UIRectEdgeNone;
如果你隐藏了navigationBar,那么你需要将所有的UIView元素上移20个点。我没有看到其他解决方法。使用自动布局会有所帮助。
这是检测iOS版本的示例代码,如果你想要向后兼容。
NSUInteger DeviceSystemMajorVersion() {
    static NSUInteger _deviceSystemMajorVersion = -1;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        NSString *systemVersion = [UIDevice currentDevice].systemVersion;
        _deviceSystemMajorVersion = [[systemVersion componentsSeparatedByString:@"."][0] intValue];
    });

   return _deviceSystemMajorVersion;
}

18
建议使用 if ([self respondsToSelector:@selector(edgesForExtendedLayout)]),而不是获取、解析和比较系统版本。 - Sebastian Hojas

15

这是我自己制作的仅有效的解决方案。

这是我的UIViewController子类:https://github.com/comonitos/ios7_overlaping

1 从UIViewController中创建子类

2 将你的window.rootViewController从该类中创建子类。

3 就这样!

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect screen = [[UIScreen mainScreen] bounds];
        if (self.navigationController) {
            CGRect frame = self.navigationController.view.frame;
            frame.origin.y = 20;
            frame.size.height = screen.size.height - 20;
            self.navigationController.view.frame = frame;
        } else {
            if ([self respondsToSelector: @selector(containerView)]) {
                UIView *containerView = (UIView *)[self performSelector: @selector(containerView)];

                CGRect frame = containerView.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                containerView.frame = frame;
            } else {
                CGRect frame = self.view.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                self.view.frame = frame;
            }
        }
    }
}

在 [self.window makeKeyAndVisible]; 代码行的下一行添加以下内容,以使您的状态栏变为白色。

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}

但是这个没有在顶部显示时间... 最大的缺点... :( - Fahim Parkar
工作得很好,但是在第4步中,您应该在视图控制器中使用preferredStatusBarStyle,因为setStatusBarStyle已被弃用,其默认操作是什么也不做。https://dev59.com/kWMk5IYBdhLWcg3wvAVo#19014724 - CpnCrunch

13
-(UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

-(void)viewWillLayoutSubviews{

 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
  {
    self.view.clipsToBounds = YES;
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenHeight = 0.0;
    if(UIDeviceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
        screenHeight = screenRect.size.height;
    else
        screenHeight = screenRect.size.width;
    CGRect screenFrame = CGRectMake(0, 20, self.view.frame.size.width,screenHeight-20);
    CGRect viewFrame1 = [self.view convertRect:self.view.frame toView:nil];
    if (!CGRectEqualToRect(screenFrame, viewFrame1))
    {
        self.view.frame = screenFrame;
        self.view.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    }
  }
}

在 plist 中添加键值对 --- View controller-based status bar appearance : NO


如果需要,更改窗口颜色。 - Darshit Shah
谢谢,它解决了我的重叠问题。但还有一个问题 - 视图控制器基于状态栏外观:NO是隐藏状态栏,我猜测。但当我将其设置为YES时,它不显示状态栏,而当我将其设置为NO时,它显示状态栏。 所以请告诉我,我的概念错了吗? - Nayan
1
我认为是因为在didFinishLaunchingWithOptions中设置了默认的半透明颜色: 'self.window.backgroundColor = [UIColor blueColor];' 并且在plist中设置了视图控制器基于状态栏外观为YES。 - Darshit Shah
很好,谢谢!还有要指出的是,苹果文档建议使用 if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_6_1) {} else {}. 干杯! - Joel Balmer
非常感谢您。您的代码对我们很有帮助。请解释一下viewWillLayoutSubviews函数。 - user3182143

4

要在iOS7中隐藏状态栏,请按照以下简单步骤:

在Xcode中进入“资源”文件夹并打开“(应用程序名称)-Info.plist文件”。

  • 检查“View controller based status bar appearance”键,并将其值设置为“NO
  • 检查“Status bar is initially hidden”键,并将其值设置为“YES

如果这些键不存在,则可以通过选择顶部的“信息属性列表”并点击+图标来添加它们。


请清楚地阅读问题,他并没有要求完全隐藏状态栏。 - ShayanK
1
@AspersionCast:他问了“有没有什么办法可以避免这种情况?” 这是其中一种避免的方法。 - Mandeep Pasbola

3
如果使用xib,一个非常简单的实现方法是将所有子视图都封装在具有调整大小标志(这些标志已经用于3.5英寸和4英寸兼容性)的容器视图中,以便视图层次结构看起来像这样: xib heirarchy 然后在viewDidLoad中,可以做如下处理:
- (void)viewDidLoad
{
  [super viewDidLoad];
  // initializations
  if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) // only for iOS 7 and above
  {
    CGRect frame = containerView.frame;
    frame.origin.y += 20;
    frame.size.height -= 20;
    containerView.frame = frame;
  }
}

这样,为了与iOS 7兼容,就不需要修改针尖。如果你有一个背景,它可以保持在containerView之外,并让它覆盖整个屏幕。

3
如果你想完全隐藏它并避免处理它,这个方法很有效。
-(BOOL) prefersStatusBarHidden
{
    return YES;
}

参考https://dev59.com/fGMl5IYBdhLWcg3wknsT#18873777

该链接提供了一个关于如何在Java中实现基于内存的缓存的答案。简单来说,它使用了LinkedHashMap,并覆盖了removeEldestEntry方法以移除最久未被访问的元素,从而避免了内存溢出。


3
这是移除状态栏所需的全部内容。 在此输入图片描述

2

导航栏:

编写以下代码:

self.navigationController.navigationBar.translucent = NO;

这个技巧对我很有帮助。


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