iOS 7-状态栏与视图重叠


109

我在ViewController里面有一个UINavigationcontroller,但是NavigationBar被隐藏了。当我在iOS 7上运行该应用程序时,状态栏显示在视图顶部。有办法避免这种情况吗?

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

在此处输入图片说明

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



2
您还需要调整y原点和增量值来处理状态栏问题,这可能会帮助您 stackoverflow.com/q/18980925/1545180
Ganapathy 2013年

Answers:


95

Xcode 5具有iOS 6/7 Deltas专门用于解决此问题的功能。在情节提要中,我将视图向下移动了20像素以在iOS 7上正确显示,为了使其与iOS 6兼容,我将其更改Delta y为-20。

在此处输入图片说明

由于我的情节提要板未使用自动布局,因此为了正确调整iOS 6上视图的高度,我必须同时设置Delta heightDelta Y


8
您的答案是正确的,但不适用于4“显示屏。如果您也可以使它适用于4”显示屏,请更新您的答案。提前致谢。

2
@AnkitMehta我不需要为4英寸
iphone

5
为我工作。请注意,要查看此增量,您必须在情节提要的“身份和类型”下取消选择“使用自动布局”。
2013年

2
我发现除了将∆Y设置为-20之外,我还必须将∆Height设置为+20
Toland Hon

3
当状态栏的高度改变时会发生什么?例:当用户激活热点等时...则高度为40px ...
Lukasz

69

如果您根本不想要任何状态栏,则需要使用以下数据更新plist:为此,请在plist中添加以下两个设置:

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

在iOS 7中,您应该在设计应用程序时考虑到透明的状态栏。例如,请参见新的iOS 7 Weather应用。


3
实际上,这是唯一的好答案,因为它以解决问题的方式将其解决了。因此:需要投票!
eleven59

5
在某些情况下可能是合适的,但是您要非常小心地隐藏状态栏。仅适用于合理的全屏视图,例如媒体播放器或图像查看器。
smileBot

1
@ eleven59,您的意思是苹果专制主义者的意图。
JohnK

1
绝对比改变视图控制器的偏移量更好(感觉很脏)。
本杰明·阿曼,

隐藏状态栏不是一个好主意...我知道这是处理iOS 7的最简单方法,但是需要时机……
Fahim Parkar 2013年

43

这是UIViewControlleriOS 7 的默认行为。该视图将为全屏显示,这意味着状态栏将覆盖视图的顶部。

如果您UIViewController在内有一个UINavigationController并且导航栏可见,则可以在您的代码中包含以下代码,viewDidLoad或者将导航栏的背景图像用于此目的。

self.edgesForExtendedLayout = UIRectEdgeNone;

如果隐藏了navigationBar,则必须通过移动20点来调整所有UIView元素。我没有看到其他解决方案。使用自动布局会有所帮助。

如果要向后兼容,这是用于检测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)])
塞巴斯蒂安奥哈斯

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;
            }
        }
    }
}

4添加它,使状态栏变为白色[self.window makeKeyAndVisible]之后;!!!

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

但这并没有显示出顶部的时间...最大的缺点... :(
Fahim Parkar 2013年

效果很好,但是对于第4步,您应该在视图控制器中使用preferredStatusBarStyle,因为不赞成setStatusBarStyle,并且它的默认操作是什么也不做。stackoverflow.com/a/19014724/1192732
CpnCrunch '16

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中添加密钥-基于视图控制器的状态栏外观:否


如果需要,可更改窗口颜色
Darshit Shah 2013年

谢谢,它解决了我的重叠问题。但是仍然存在一个问题-基于视图控制器的状态栏外观:我猜是不会隐藏状态栏。但是,当我将其设置为“是”时,则不显示状态栏;当我将其设置为“否”时,则将显示状态栏。所以请告诉我我在概念上错了还是什么?
Nayan 2014年

1
我认为是因为在didFinishLaunchingWithOptions'self.window.backgroundColor = [UIColor blueColor];'中设置了默认的半透明颜色。并在plist中设置基于视图控制器的状态栏外观是
Darshit Shah 2014年

很好,谢谢!另外,仅指出苹果文档建议您是否检查(NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_6_1){} else {}。干杯!
乔尔·巴尔默

非常感谢您。您的代码对我们有帮助。请解释一下viewWillLayoutSubviews函数。
user3182143 '16

4

要在ios7中隐藏状态栏,请执行以下简单步骤:

在Xcode中,转到“ Resources”文件夹并打开“ (app name)-Info.plist file”。

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

如果没有按键,则可以通过information property list在顶部选择“ ”并单击+图标来添加它


清楚地阅读问题,他没有要求完全隐藏状态栏。
ShayanK 2014年

1
@AspersionCast:他问“有办法避免这种情况吗?” 这是避免这种情况的方法之一。
Mandeep Pasbola 2014年


3

如果使用xibs,一个非常简单的实现是使用调整大小标志将所有子视图封装在容器视图内(您将已经使用它们来实现3.5“和4”兼容性),以便视图层次结构看起来像这样

希伯氏体系

然后在中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并使其覆盖整个屏幕。



2

对于导航栏:

编写此代码:

self.navigationController.navigationBar.translucent = NO;

只是为我做了把戏。


1

文森特的答案edgeForExtendedLayout对我有用。

这些宏有助于确定os版本,从而使其更容易

// 7.0 and above 
#define IS_DEVICE_RUNNING_IOS_7_AND_ABOVE() ([[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending) 

// 6.0, 6.0.x, 6.1, 6.1.x
#define IS_DEVICE_RUNNING_IOS_6_OR_BELOW() ([[[UIDevice currentDevice] systemVersion] compare:@"6.2" options:NSNumericSearch] != NSOrderedDescending) 

将这些宏添加到项目的prefix.pch文件中,可以在任何地方访问

if(IS_DEVICE_RUNNING_IOS_7_AND_ABOVE())
{
 //some iOS 7 stuff
 self.edgesForExtendedLayout = UIRectEdgeNone;
}

if(IS_DEVICE_RUNNING_IOS_6_OR_BELOW())
{
 // some old iOS stuff
}

1
对我来说self.edgesForExtendedLayout = UIRectEdgeNone; 不起作用...为什么有任何原因?
Fahim Parkar


0

如果您希望不惜一切代价启用“使用自动版式”,请将以下代码放在viewdidload中。

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
{
        self.edgesForExtendedLayout = UIRectEdgeNone;
        self.extendedLayoutIncludesOpaqueBars = NO;
        self.automaticallyAdjustsScrollViewInsets = NO;
}

0

从YTPlayer的风景视图返回后,我的状态栏和导航栏重叠。这是我尝试@comonitos版本后的解决方案,但无法在我的iOS 8上运行

- (void)fixNavigationBarPosition {
    if (self.navigationController) {
        CGRect frame = self.navigationController.navigationBar.frame;
        if (frame.origin.y != 20.f) {
            frame.origin.y = 20.f;
            self.navigationController.navigationBar.frame = frame;
        }
    }
}

只要您想固定导航栏的位置,只需调用此函数。我在YTPlayerViewDelegate的playerView:didChangeToState:

- (void)playerView:(YTPlayerView *)playerView didChangeToState:(YTPlayerState)state {
    switch (state) {
        case kYTPlayerStatePaused:
        case kYTPlayerStateEnded:
            [self fixNavigationBarPosition];
            break;
        default:
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.