ChatGPT解决这个技术问题 Extra ChatGPT

iOS 7 状态栏在 iPhone 应用程序中回到 iOS 6 默认样式?

在 iOS 7 中,UIStatusBar 的设计方式使其与视图合并,如下所示:

https://i.stack.imgur.com/rfo0Q.png

这很酷,但是当您在视图的顶部有一些东西时,它会有点混乱您的视图,并且它会与状态栏重叠。

是否有一个简单的解决方案(例如在 info.plist 中设置属性)可以将其工作方式 [不重叠] 更改回 iOS6 中的方式?

我知道一个更直接的解决方案是为每个视图控制器设置 self.view.center.x + 20 个点,但是更改它们会搞砸其他维度(具有不同的 self.view.center.x 可能会导致自定义 segues 出现问题等),突然间它变成了一项最好避免的乏味工作。

如果有人可以为此提供一个单行解决方案,我将非常高兴。

PS我知道我可以通过做一些事情来隐藏状态栏

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];

didFinishLaunchingWithOptions 方法中,但这是一种解决方法,是避免问题的捷径,所以我不认为这是一个真正的解决方案。

可悲的是黑色状态栏在 ios 7 中已被弃用
我同意@GangstaGraham。那些颜色简直太美了!要回答你的问题,恐怕你不能。之所以现在这样设计状态栏,是因为半透明是 iOS 的新事物,它旨在通过说它位于某物之上,从而赋予应用程序“深度”,因此下方有一些东西。
您是否尝试过将 preferredStatusBarStyle 设置为 UIStatusBarDefault?结帐 iOS 7 UIViewController Documentation
为状态栏设置 UIStatusBarDefault 只会使其内容变黑。它不会使其功能恢复到 iOS6 中的方式。
这有什么好运气吗?我喜欢iOS7,但这件事让我发疯了!

j
jaredsinclair

这是从 a blog post I wrote 交叉发布的,但这里是 iOS 7 上状态栏、导航栏和容器视图控制器的完整概要:

没有办法保留 iOS 6 风格的状态栏布局。在 iOS 7 上,状态栏将始终与您的应用程序重叠 不要将状态栏外观与状态栏布局混淆。外观(浅色或默认)不会影响状态栏的布局方式(框架/高度/重叠)。还需要注意的是,系统状态栏不再有任何背景颜色。当 API 引用 UIStatusBarStyleLightContent 时,它们表示清晰背景上的白色文本。 UIStatusBarStyleDefault 是清晰背景上的黑色文本。状态栏外观由两个互斥的基础路径之一控制:您可以以传统方式以编程方式设置它们,或者 UIKit 将根据 UIViewController 的一些新属性为您更新外观。后一个选项默认开启。检查您应用的 plist 值是否为“基于 ViewController 的状态栏外观”,以查看您使用的是哪一个。如果将此值设置为 YES,则应用程序中的每个顶级视图控制器(标准 UIKit 容器视图控制器除外)都需要覆盖首选状态栏样式,返回默认样式或灯光样式。如果将 plist 值编辑为 NO,则可以使用熟悉的 UIApplication 方法管理状态栏外观。 UINavigationController 将根据一组相当奇怪且未记录的约束将其 UINavigationBar 的高度更改为 44 点或 64 点。如果 UINavigationController 检测到其视图框架的顶部与其 UIWindow 的顶部在视觉上是连续的,那么它会绘制高度为 64 磅的导航栏。如果其视图的顶部与 UIWindow 的顶部不连续(即使仅相差一个点),则它以“传统”方式绘制其导航栏,高度为 44 点。这个逻辑由 UINavigationController 执行,即使它是应用程序的视图控制器层次结构中的几个子级。没有办法阻止这种行为。如果您提供一个只有 44 点(88 像素)高的自定义导航栏背景图像,并且 UINavigationController 的视图边界与 UIWindow 的边界匹配(如 #4 中所述),则 UINavigationController 将在框架中绘制您的图像(0,20,320 ,44),在您的自定义图像上方留下 20 点不透明的黑色空间。这可能会让您误以为自己是绕过规则 1 的聪明开发人员,但您错了。导航栏仍然是 64 点高。在滑动显示样式视图层次结构中嵌入 UINavigationController 可以使这一点非常清晰。当心 UIViewController 的命名混淆的 edgesForExtendedLayout 属性。在大多数情况下,调整 edgeForExtendedLayout 没有任何作用。 UIKit 使用此属性的唯一方法是,如果您将视图控制器添加到 UINavigationController,则 UINavigationController 使用 edgesForExtendedLayout 来确定其子视图控制器是否应该在导航栏/状态栏区域下方可见。在 UINavigationController 本身上设置 edgesForExtendedLayout 不会改变 UINavigationController 是否具有 44 点或 64 点高的导航栏区域。有关该逻辑,请参见#4。使用工具栏或 UITabBarController 时,类似的布局逻辑适用于视图的底部。如果您要做的只是防止您的自定义子视图控制器在 UINavigationController 内覆盖导航栏,则将 edgesForExtendedLayout 设置为 UIRectEdgeNone(或至少一个不包括 UIRectEdgeTop 的掩码)。在视图控制器的生命周期中尽早设置此值。 UINavigationController 和 UITabBarController 还将尝试在其子视图层次结构中填充表视图和集合视图的 contentInsets。它以类似于#4 中的状态栏逻辑的方式执行此操作。有一种编程方式可以防止这种情况发生,通过将表视图和集合视图的自动调整滚动视图插入设置为否(默认为是)。这给 Whisper 和 Riposte 带来了一些严重的问题,因为我们使用 contentInset 调整来控制表格视图的布局以响应工具栏和键盘的移动。重申一下:没有办法回到 iOS 6 风格的状态栏布局逻辑。为了近似这一点,您必须将应用程序的所有视图控制器移动到从屏幕顶部偏移 20 个点的容器视图中,在状态栏后面故意留下黑色视图以模拟旧外观。这是我们最终在 Riposte 和 Whisper 中使用的方法。 Apple 正在努力确保您不会尝试执行 #9。他们希望我们重新设计所有应用程序以覆盖状态栏。然而,出于用户体验和技术原因,有许多令人信服的论点,为什么这并不总是一个好主意。您应该为您的用户做最好的事情,而不是简单地跟随平台的奇思妙想。


只是想补充一点,您可以将约束添加到视图顶部的任何内容以附加到顶部布局指南 - 这将在状态栏后面留下一个空白区域(您可以用您想要的任何颜色填充)但也将允许视图在 iOS 6 中自动调整到正确的位置。这样您就不必在代码中手动调整视图的位置。
这是一个绝妙的解决方案。你暴露了我对 AutoLayout 的无知。最好坚持下去。
如果您将对象的顶部空间放置在顶部布局指南的边缘下方,您可以使用约束控件将垂直间距约束添加到最近的邻居,这将成为顶部布局指南。或者,您可以使用 ctrl+click 从您的对象到顶部布局指南显式添加垂直间距约束。
@BreadicalMD 我不明白的一部分是 -topLayoutGuide 在 iOS 6 上不可用,这是否意味着您需要在 iOS 7 和 6 上使用不同的自动布局约束?
很好的答案......但我有一个疑问 1) UINavigationController 改变高度部分。请多解释一下。谢谢
E
ErickBergmann

2013 年 9 月 19 日更新:通过添加 self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height) 来修复缩放错误;更正了 NSNotificationCenter 语句中的错别字

2013 年 9 月 12 日更新:将 UIViewControllerBasedStatusBarAppearance 更正为 NO 添加了针对具有屏幕旋转的应用程序的解决方案 添加了更改状态栏背景颜色的方法。

显然,没有办法将 iOS7 状态栏恢复到它在 iOS6 中的工作方式。

但是,我们总是可以编写一些代码并将状态栏变成类似 iOS6 的,这是我能想到的最短方法:

在 info.plist 中将 UIViewControllerBasedStatusBarAppearance 设置为 NO (选择不让视图控制器调整状态栏样式,以便我们可以使用 UIApplicationstatusBarStyle 方法设置状态栏样式。)在 AppDelegate 的 application:didFinishLaunchingWithOptions 中,调用 if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { [应用程序 setStatusBarStyle:UIStatusBarStyleLightContent]; self.window.clipsToBounds =是; self.window.frame = CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height-20); //2013 年 9 月 19 日添加 self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height); } 返回是;

为了:

检查它是否是 iOS 7。将状态栏的内容设置为白色,而不是 UIStatusBarStyleDefault。避免显示其框架超出可见边界的子视图(对于从顶部动画到主视图的视图)。通过移动和调整应用程序的窗口框架大小来创建状态栏占用空间的错觉,就像它在 iOS 6 中一样。

对于具有屏幕旋转功能的应用,

使用 NSNotificationCenter 通过添加来检测方向变化

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidChangeStatusBarOrientation:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];

if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) 中并在 AppDelegate 中创建一个新方法:

- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification
{
    int a = [[notification.userInfo objectForKey: UIApplicationStatusBarOrientationUserInfoKey] intValue];
    int w = [[UIScreen mainScreen] bounds].size.width;
    int h = [[UIScreen mainScreen] bounds].size.height;
    switch(a){
        case 4:
            self.window.frame =  CGRectMake(0,20,w,h);
            break;
        case 3:
            self.window.frame =  CGRectMake(-20,0,w-20,h+20);
            break;
        case 2:
            self.window.frame =  CGRectMake(0,-20,w,h);
            break;
        case 1:
           self.window.frame =  CGRectMake(20,0,w-20,h+20);
    }
}

这样当方向改变时,它会触发一个 switch 语句来检测应用的屏幕方向(Portrait、Upside Down、Landscape Left 或 Landscape Right)并分别改变应用的窗口框架以创建 iOS 6 状态栏错觉。

要更改状态栏的背景颜色:

添加

 @property (retain, nonatomic) UIWindow *background;

AppDelegate.h 中使 background 成为您的类中的属性并防止 ARC 释放它。 (如果您不使用 ARC,则不必这样做。)

之后,您只需在 if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) 中创建 UIWindow:

background = [[UIWindow alloc] initWithFrame: CGRectMake(0, 0, self.window.frame.size.width, 20)];
background.backgroundColor =[UIColor redColor];
[background setHidden:NO];

@implementation AppDelegate 之后不要忘记 @synthesize background;


这会在旋转时中断。只是一个提醒
@JesseNaugher 我建议以编程方式将垂直间距约束从 0 修改为 20。它将在旋转中起作用。
关于如何避免导航栏扩大 20 像素的任何想法?这个解决方案对我来说很好,但我的导航栏太高了 20 像素。
@ArchyHolt:您的简单解决方案对我有用,除非我提供模态视图控制器。一旦模态视图控制器被解除,剩余的视图现在位于状态栏下方。我已经在一个新的示例项目中复制了这一点,以确保没有其他时髦的事情发生。我在想也许你更高级的解决方案在这里可能有用,但不确定什么通知会起作用。有任何想法吗?
关闭模式视图控制器后视图会重置。 :(
E
ErickBergmann

UPDATE(NEW SOLUTION) 本次更新是iOS 7导航栏问题的最佳解决方案。您可以设置导航栏颜色示例:FakeNavBar.backgroundColor = [UIColor redColor];注意:如果您使用默认导航控制器,请使用旧解决方案。 AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    if(NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_7_0)
    {
        UIView *FakeNavBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
        FakeNavBar.backgroundColor = [UIColor whiteColor];

        float navBarHeight = 20.0;
        for (UIView *subView in self.window.subviews) {

            if ([subView isKindOfClass:[UIScrollView class]]) {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height - navBarHeight);
            } else {
                subView.frame = CGRectMake(subView.frame.origin.x, subView.frame.origin.y + navBarHeight, subView.frame.size.width, subView.frame.size.height);
            }
        }
        [self.window addSubview:FakeNavBar];
    }

    return YES;

}

旧解决方案 - 如果您使用以前的代码,请忽略以下代码和图像这是旧版本的 iOS 7 导航栏解决方案。

我用下面的代码解决了这个问题。这是用于添加状态栏。 didFinishLaunchingWithOptions

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    UIView *addStatusBar = [[UIView alloc] init];
    addStatusBar.frame = CGRectMake(0, 0, 320, 20);
    addStatusBar.backgroundColor = [UIColor colorWithRed:0.973 green:0.973 blue:0.973 alpha:1]; //change this to match your navigation bar
    [self.window.rootViewController.view addSubview:addStatusBar];
}

对于Interface Builder,这是在您使用 iOS 6 时打开的;它从 0 像素开始。

注意:iOS 6/7 Delta 仅在您在详细信息窗格的“文件检查器”(最左侧的图标)中取消选中视图控制器的“使用自动布局”时才会出现。

https://i.stack.imgur.com/Qa800.png


你成就了我的一天。请 +1 寻求帮助!
请注意:iOS 6/7 Delta 仅在您取消选中详细信息窗格中“文件检查器”(最左侧图标)中视图控制器的“使用自动布局”时才会出现。
非常感谢!你给我省了很多麻烦!
谁说无法维护 iOS 6 样式的状态栏布局,您可以通过@TacettinÖzbölük 方式做到这一点……感谢 mate 提供的这个 awsum 解决方案。
好东西!另外,请注意苹果现在更喜欢这个:if (NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_6_1) {}
A
Adrian P

解决方案 :

通过覆盖方法将其设置在您的视图控制器或根视图控制器中:

-(BOOL) prefersStatusBarHidden
    {
        return YES;
    }

不错的解决方案。完全删除栏。可能并不总是适合 UX,但可行。
就是棒。完美无瑕地为我工作。
场景:当我在全屏播放视频后切换回我的 UIVIew 时,底部会出现一个黑条,它只是状态栏的大小,尽管我已经在使用状态栏了。我完全删除了状态栏,现在问题已解决。
我只用这种方法成功了
1
14 revs, 2 users 99%

这是广泛使用情节提要的项目的另一种方法:

目标:

这种方法的目标是在 iOS7 中重新创建与 iOS6 中相同的状态栏样式(请参阅问题标题“iOS 7 状态栏回到 iOS 6 样式?”)。

概括:

为了实现这一点,我们通过向下移动与状态栏(在 iOS 7 下)重叠的 UI 元素来尽可能地使用 Storyboard,同时使用增量来恢复 iOS 6.1 或更早版本的向下布局更改。然后,在 iOS 7 中产生的额外空间被一个 UIView 占用,其中 backgroundColor 设置为我们选择的颜色。后者可以在代码中创建或使用情节提要(请参阅下面的替代方案)

假设:

为了在执行以下步骤时获得所需的结果,假设 View controller-based status bar appearance 设置为 NO,并且您的 Status bar style 设置为“透明黑色样式(alpha of 0.5)”或“不透明黑色样式”。这两个设置都可以在项目设置的“信息”下找到/或添加。

脚步:

将子视图添加到 UIWindow 以用作您的状态栏背景。为此,将以下内容添加到 AppDelegate 的应用程序中: didFinishLaunchingWithOptions: after makeKeyAndVisible if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { UIView *statusBarBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, yourAppsUIWindow.frame.size.width, 20) ]; statusBarBackgroundView.backgroundColor = [UIColor blackColor]; [yourAppsUIWindow addSubview:statusBarBackgroundView]; }

由于您仅以编程方式为 iOS 7 添加了背景,因此您必须相应地调整与状态栏重叠的 UI 元素的布局,同时保留它们的 iOS6 布局。为此,请执行以下操作: 确保未选中 Storyboard 的 Use Autolayout(这是因为“iOS 6/7 Deltas”不会显示在 Size Inspector 中)。为此: 选择您的 Storyboard 文件 显示实用程序 选择“显示文件检查器” 在“界面生成器文档”下取消选中“使用自动布局” 或者,为了帮助您在应用 iOS 7 和 6 时监控布局更改,请选择“Assistant Editor”,选择“Preview”和“iOS 6.1 或更早版本”:现在选择您要调整的 UI 元素,使其不再与状态栏重叠 在 Utilities 列中选择“Show the Size Inspector”重新定位您的沿 Y 轴的 UI 元素与状态栏背景高度相同:并将 Y 的 iOS6/7 Deltas 值更改为与状态栏背景高度相同的 NEGATIVE 量(如果您是,请注意 iOS 6 预览中的更改使用它):

确保未选中 Storyboard 的 Use Autolayout(这是因为“iOS 6/7 Deltas”不会显示在 Size Inspector 中)。为此:选择您的 Storyboard 文件 show Utilities 选择“Show the File Inspector” 在“Interface Builder Document”下取消选中“Use Autolayout”

选择您的故事板文件

显示实用程序

选择“显示文件检查器”

在“Interface Builder Document”下取消选中“Use Autolayout”

或者,为了帮助您在应用它们时监控 iOS 7 和 6 的布局更改,请选择“Assistant Editor”,选择“Preview”和“iOS 6.1 或更早版本”:

现在选择您要调整的 UI 元素,使其不再与状态栏重叠

在 Utilities 列中选择“Show the Size Inspector”

将 UI 元素沿 Y 轴重新定位,与状态栏 bg 高度相同:

并将 Y 的 iOS6/7 Deltas 值更改为与状态栏 bg 高度相同的 NEGATIVE 量(如果您使用它,请注意 iOS 6 预览中的更改):

备择方案:

要在情节提要繁重的项目中添加更少的代码并让状态栏背景自动旋转,而不是以编程方式为状态栏添加背景,您可以为位于所述视图控制器主视图顶部的每个视图控制器添加一个彩色视图。然后,您可以将此新视图的高度增量更改为与您的视图高度相同的负数(使其在 iOS 6 下消失)。

这种替代方案的缺点(尽管考虑到自动旋转兼容性可能可以忽略不计)是,如果您正在查看 iOS 6 的 Storyboard,则不会立即看到这个额外的视图。只有查看“故事板的文档大纲”。


P
Peter Mortensen

如果您不希望视图控制器与状态栏(和导航栏)重叠,请取消选中 Xcode 5 中 Interface Builder 中的“在顶部栏下延伸边缘”框。

https://i.stack.imgur.com/LBSsZ.png


这只有在您使用情节提要时才有可能
它仅适用于容器 vcs,例如导航控制器或标签栏控制器
edgeForExtendedLayout 仅由容器视图控制器(如 UINavigationController)使用,以确定它的子视图是否应与父 chrome 重叠。在 UIWindow 的根视图控制器上设置此属性不会执行任何操作。请参阅上面的答案:stackoverflow.com/questions/18294872/…
你如何为 UITabBarController @Andrea 做到这一点?谢谢。
@KarenAnne 取决于您以编程方式还是使用故事板。以编程方式,您只需将edgeForExtent 属性设置为您在UITabBarViewController 中显示的视图控制器中您喜欢的属性,但是为了不出现状态栏问题,您必须在第UITabbarController 中加载一个uinavigationcontroller。在这里检查。 developer.apple.com/library/ios/documentation/UserExperience/…
C
Cœur

Apple 发布了Technical Q&A QA1797: Preventing the Status Bar from Covering Your Views。它适用于 iOS 6 和 iOS 7 版本。


苹果假设每个人都在使用自动布局。自动布局在 Xcode 4 中很糟糕,而 Xcode 5 才刚刚发布,所以这是一个可疑的假设。
但在未来,这是一个更好的解决方案,然后调整根窗口或状态栏的框架。
据我所知,如果您的 rootViewController 是 splitViewController,Apple 的解决方案将不起作用。
P
Peter Mortensen

我已经查看了很多很多很多很多教程来解决这个该死的问题。但它们都不起作用!这是我的解决方案,它对我有用:

if( [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f ) {
    float statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
    for( UIView *v in [self.view subviews] ) {
        CGRect rect = v.frame;
        rect.origin.y += statusBarHeight;
        v.frame = rect;
    }
}

逻辑很简单。我将 self.view 上的所有子视图移动 20 像素。就这样。然后,屏幕截图将像 iOS 6 一样显示。我讨厌iOS7的状态栏! ~~"~


我应该在哪里添加这个?在应用程序委托中确实启动了选项?
当我这样做时,我的状态栏变成白色
C
Cœur

Archy Holt 答案的一个小替代方案,更简单一点:

一个。在 info.plist 中将 UIViewControllerBasedStatusBarAppearance 设置为 NO

湾。在 AppDelegateapplication:didFinishLaunchingWithOptions: 中,调用:

if ([[UIDevice currentDevice].systemVersion floatValue] < 7)
{
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
}
else
{
    // handling statusBar (iOS7)
    application.statusBarStyle = UIStatusBarStyleLightContent;
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    self.window.clipsToBounds = YES;

    // handling screen rotations for statusBar (iOS7)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidChangeStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}

并添加方法:

- (void)applicationDidChangeStatusBarOrientationNotification:(NSNotification *)notification
{
    // handling statusBar (iOS7)
    self.window.frame = [UIScreen mainScreen].applicationFrame;
}

您还可以考虑将 UIWindow 子类化以处理 UIApplicationDidChangeStatusBarOrientationNotification 本身。


你有问题 presentViewController:animated:completion: 吗?
@TùngĐỗ 是的,所以我做了一个更好的替代方案:stackoverflow.com/questions/18294872/…
I
IgniteCoders

我在我所有的视图控制器中都使用了它,它很简单。在所有 viewDidLoad 方法中添加以下行:

- (void)viewDidLoad{
    //add this 2 lines:
    if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

    [super viewDidLoad];
}

像魅力一样工作,而且很容易。在 ruby 运动中,在调用 super 之前使用: self.edgesForExtendedLayout = UIRectEdgeNone if respondsToSelector("edgesForExtendedLayout")
R
Rajesh Loganathan

试试这个简单的方法......

第 1 步:更改单个 viewController

[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque];

第 2 步:更改整个应用程序

info.plist
      ----> Status Bar Style
                  --->UIStatusBarStyle to UIStatusBarStyleBlackOpaque

第 3 步:还要在每个 viewWillAppear 中添加此项以调整 iOS7statusbar 高度

    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 7) {
        CGRect frame = [UIScreen mainScreen].bounds;
        frame.origin.y+=20.0;
        frame.size.height-= 20.0;
        self.view.frame = frame;
        [self.view layoutIfNeeded];
    }

C
Community

Interface Builder 中有一个选项调用 iOS 6/7 Delta 属性,旨在解决偏移问题。

在 Stack Overflow 问题中查看它Interface Builder: What are the UIView's Layout iOS 6/7 Deltas for?


F
Fahim Parkar

我在 iOS 7 中实现了类似 iOS 6 的状态栏。

在 info.plist 中将 UIViewControllerBasedStatusBarAppearance 设置为 NO

将此代码粘贴到 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    [application setStatusBarStyle:UIStatusBarStyleLightContent];
    self.window.clipsToBounds =YES;
    self.window.frame =  CGRectMake(0,20,self.window.frame.size.width,self.window.frame.size.height);

    //Added on 19th Sep 2013
    NSLog(@"%f",self.window.frame.size.height);
    self.window.bounds = CGRectMake(0,0, self.window.frame.size.width, self.window.frame.size.height);
}

它可能会将您的所有视图下推 20 像素。要克服在 -(void)viewDidAppear:(BOOL)animated 方法中使用以下代码

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    CGRect frame=self.view.frame;
    if (frame.size.height==[[NSUserDefaults standardUserDefaults] floatForKey:@"windowHeight"])
    {
        frame.size.height-=20;
    }
    self.view.frame=frame;
}

您必须在窗口分配后在 didFinishLauncing 方法中设置 windowHeight Userdefaults 值,例如

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[[NSUserDefaults standardUserDefaults] setFloat:self.window.frame.size.height forKey:@"windowHeight"];

更好的方法是使 UINavigationBar 的 height 等于 64 而不是 44。然后您的栏将一直延伸到顶部,就像在 Apple 的应用程序中一样。
@AaronBrager 但我的要求是显示 iOS 6 风格的状态栏。
能否请您添加横向方向 iOS 7 的解决方案?我也在做同样的事情。但它不适用于 iOS 7 Landscape。
@DesertRose THX!这对我有用,但它切断了底部的 uitabbar。我有一个基于标签栏控制器的应用程序,它有 3 个视图,其中 2 个是 tableviewcontrollers。
直到我旋转设备(我的 iOS 7 设备是 iPad),这完美地修复了它。但是一旦我旋转,黑条就会保持在原来的位置,并且“视图”(对不起,如果这是错误的技术术语,我是 PhoneGap/web 人)保持其缩小的高度——除了它不再是高度,而是宽度。此解决方案不支持旋转,但它是我见过的最好的修复 - 如何改进它以观察设备旋转?谢谢!
t
thebman

如果您使用的是界面生成器,请尝试以下操作:

在您的 xib 文件中:

1)选择主视图,将背景颜色设置为黑色(或您希望状态栏为任何颜色

2)确保背景是一个独立的子视图,定位为控制器视图的顶级子视图。移动您的背景以成为控制器视图的直接子级。检查自动调整大小面板以确保您已锁定所有框架边缘,激活两个灵活性轴,如果这是 UIImageView,请将内容模式设置为 Scale to fill。以编程方式,这将转换为 contentMode 设置为 UIViewContentModeScaleToFill 并将其自动调整大小掩码设置为 (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)。

3) 现在将所有被锁定的东西从上向下移动 20 分,并将 iOS 6/7 delta Y 设置为 -20。所有在自动调整大小面板中锁定到顶部框架的顶级子项都需要向下移动 20pts 并将其 iOS 6/7 delta Y 设置为 -20。 (Cmd 选择所有这些,然后单击向下箭头 20 次 - 有没有更好的方法?)

4) 调整以上所有具有灵活高度的项目的 iOS 6/7 增量高度。任何锁定到框架顶部和底部并在自动调整大小面板中启用了灵活高度的项目也必须将其 iOS 6/7 增量高度设置为 20。这包括上面提到的背景视图。这似乎违反直觉,但由于应用这些顺序,这是必要的。首先设置帧高度(基于设备),然后应用增量,最后根据所有子帧的偏移位置应用自动调整大小的掩码 - 仔细考虑一下,这将是有意义的。

5)最后,锁定到底部框架但不是顶部框架的项目根本不需要增量。

这将在 iOS7 和 iOS6 中为您提供相同的状态栏。

另一方面,如果您希望在保持 iOS6 兼容性的同时使用 iOS7 样式,则将背景视图的 delta Y / delta height 值设置为 0。

要查看更多 iOS7 迁移信息,请阅读完整帖子:http://uncompiled.blogspot.com/2013/09/legacy-compatible-offsets-in-ios7.html


使用自动布局时没有增量
A
Alexandre OS

我的解决方案是在 iOS 7 上在窗口顶部添加一个高度为 20 点的 UIView。然后我在 AppDelegate 类中创建了一个方法来显示/隐藏“实心”状态栏背景。在 application:didFinishLaunchingWithOptions: 中:

// ...

// Add a status bar background
self.statusBarBackground = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.window.bounds.size.width, 20.0f)];
self.statusBarBackground.backgroundColor = [UIColor blackColor];
self.statusBarBackground.alpha = 0.0;
self.statusBarBackground.userInteractionEnabled = NO;
self.statusBarBackground.layer.zPosition = 999; // Position its layer over all other views
[self.window addSubview:self.statusBarBackground];

// ...
return YES;

然后我创建了一个淡入/淡出黑色状态栏背景的方法:

- (void) showSolidStatusBar:(BOOL) solidStatusBar
{
    [UIView animateWithDuration:0.3f animations:^{
        if(solidStatusBar)
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
            self.statusBarBackground.alpha = 1.0f;
        }
        else
        {
            [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
            self.statusBarBackground.alpha = 0.0f;
        }
    }];
}

我现在要做的就是在需要时调用 [appDelegate showSolidStatusBar:YES]


S
Selvin

如果您使用自动布局,这可能是一个压倒性的问题,因为您不能再直接操作框架。有一个简单的解决方案,无需太多工作。

我最终在实用程序类中编写了一个实用程序方法,并从所有视图控制器的 viewDidLayoutSubviews 方法中调用它。

+ (void)addStatusBarIfiOS7:(UIViewController *)vc
    {
        if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
            CGRect viewFrame = vc.view.frame;
            if(viewFrame.origin.y == 20) {
                //If the view's y origin is already 20 then don't move it down.
                return;
            }
            viewFrame.origin.y+=20.0;
            viewFrame.size.height-= 20.0;
            vc.view.frame = viewFrame;
            [vc.view layoutIfNeeded];
        }
    }

在需要状态栏的视图控制器中覆盖您的 viewDidLayoutSubviews 方法。它会让你摆脱自动布局的负担。

- (void)viewDidLayoutSubviews
{
    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];
    [super viewDidLayoutSubviews];
    [MyUtilityClass addStatusBarIfiOS7:self];
}

m
marcelosalloum

最简单的方法是将旧的 SDK 安装到最新的 Xcode。

如何将旧版 SDK 安装到最新版 Xcode?

您可以从 http://www.4shared.com/zip/NlPgsxz6/iPhoneOS61sdk.html 获取 iOS 6.1 SDK 或下载较旧的 Xcode 并从其内容中获取 SDK 解压缩并将此文件夹粘贴到 /Applications/Xcode.app/ Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs 重启 xcode。您现在可以在项目的构建设置中选择较旧的 SDK

希望它可以帮助你。它对我有用=)


为我工作。谢谢@marcelosalloum,但仍在为我的phonegap(uiwebview)应用程序寻找解决方法,以支持iOS7的透明状态栏,以便将来更新我的应用程序。再次感谢。 ;)
@marcellosaloum,您确定该应用会被 Apple 接受吗?他们说使用 XCode 4 编译的应用程序将不再被接受……这实际上意味着 iOS 6 SDK。
我的应用确实被接受了,因为 Xcode5 可以编译较旧的 iOS SDK。我不确定 AppStore 是否会拒绝 Xcode4 构建的应用程序,但 (Xcode4 != iOS 6 SDK) 如您所说。
是在2月1日之后吗?在那一天,Apple 强制执行此操作。
不,去年最后一次接触到那个代码,伙计们。不知道苹果已经强制执行(虽然不高兴知道)。你能把上面说的链接贴在这里吗?干杯
C
Cœur

由于使用 presentViewController:animated:completion: 搞砸了 window.rootViewController.view,我不得不找到一种不同的方法来解决这个问题。通过子类化我的 rootViewController 的 UIView,我终于让它与模态和旋转一起工作。

。H

@interface RootView : UIView

@end

.m

@implementation RootView

-(void)setFrame:(CGRect)frame
{
    if (self.superview && self.superview != self.window)
    {
        frame = self.superview.bounds;
        frame.origin.y += 20.f;
        frame.size.height -= 20.f;
    }
    else
    {
        frame = [UIScreen mainScreen].applicationFrame;
    }

    [super setFrame:frame];
}

- (void)layoutSubviews
{
    self.frame = self.frame;

    [super layoutSubviews];
}

@end

您现在有一个强大的 iOS7 动画解决方法。


V
Vizllx

我迟到了这个答案,但我只想分享我所做的,这基本上是最简单的解决方案

首先->转到您的 info.plist 文件并添加状态栏样式->透明黑色样式(Alpha of 0.5)

现在,它开始了:-

将此代码添加到您的 AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
     //Whatever your code goes here
  if(kDeviceiPad){

     //adding status bar for IOS7 ipad
         if (IS_IOS7) {
              UIView *addStatusBar = [[UIView alloc] init];
              addStatusBar.frame = CGRectMake(0, 0, 1024, 20);
              addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //change this to match your navigation bar
              [self.window.rootViewController.view addSubview:addStatusBar];
                    }
                }
    else{

         //adding status bar for IOS7 iphone
        if (IS_IOS7) {
            UIView *addStatusBar = [[UIView alloc] init];
            addStatusBar.frame = CGRectMake(0, 0, 320, 20);
            addStatusBar.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; //You can give your own color pattern
            [self.window.rootViewController.view addSubview:addStatusBar];
        }

    return YES;
   }

j
jki

我非常简单的解决方案(假设您只支持垂直方向)是在 App 委托的 didFinishLaunchingWithOptions 方法中为低于 7 的 iOS 版本重新定义应用程序窗口边界:

CGRect screenBounds = [[UIScreen mainScreen] bounds];
if ([HMService getIOSVersion] < 7) {
    // handling statusBar (iOS6) by leaving top 20px for statusbar.
    screenBounds.origin.y = 20;
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}
else {
    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
}

您的代码只是将“y”从 0 移动到 20,但不会相应地调整高度,因此您应该添加 screenBounds.size.height -= 20;就在 screenBounds.origin.y = 20 之后;
P
Peter Mortensen

您可以一起隐藏状态栏。所以你的应用程序将是全屏的。我认为这是你会得到的最好的。

UIStatusBarStyleNone 或在目标设置中设置。


在哪里指定 UIStatusbarstylenone
c
chandrika

在 iOS 7 中隐藏状态栏的步骤:

1.转到您的应用程序 info.plist 文件。

2.设置,查看基于控制器的状态栏外观:Boolean NO

希望我解决了状态栏问题.....


T
Tomer Even

为了继续使用 setStatusBarHidden:我使用这个类别:

@interface UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden;

@end

@implementation UIApplication (StatusBar)

-(void)setIOS7StatusBarHidden:(BOOL)statusBarHidden{
    if (!IOS7) {
        [self setStatusBarHidden:statusBarHidden];
        return;
     }

    if ([self isStatusBarHidden] == statusBarHidden) {
        return;
    }

    [self setStatusBarHidden:statusBarHidden];
    [self keyWindow].clipsToBounds = YES;
    CGFloat offset = statusBarHidden ? 0 : 20;
    [self keyWindow].frame =  CGRectMake(0,offset,[self keyWindow].frame.size.width,[self keyWindow].frame.size.height-offset);
    [self keyWindow].bounds = CGRectMake(0, offset, [self keyWindow].frame.size.width,[self keyWindow].frame.size.height);
}

@end

s
simbesi.com

我发现这里是 iOS7 中此导航栏问题的最佳替代方案和解决方案!

http://www.appcoda.com/customize-navigation-status-bar-ios-7/

我希望它能消除我们所有的疑问和担忧。


c
channi

分享这可能为时已晚,但我有一些可以帮助某人的东西,我试图对 UINavigationBar 进行子类化,并想让它看起来像带有黑色状态栏和白色状态栏文本的 ios 6。

这是我发现的工作

        self.navigationController?.navigationBar.clipsToBounds = true
        self.navigationController?.navigationBar.translucent = false
        self.navigationController?.navigationBar.barStyle = .Black
        self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()

它使我的状态栏背景为黑色,状态栏文本为白色,导航栏的颜色为白色。

iOS 9.3、XCode 7.3.1