5

为 iOS7 更新我的应用程序时,UI 出现在状态栏区域内。请参阅下图中的“关于我们”和搜索按钮。

在此处输入图像描述

在 iOS6 中,它从状态栏下方的正确位置开始。请注意,我以编程方式创建了这个 UI,而不是从情节提要。

我找到了以下解决方案并将其放在我的视图控制器中,但它不起作用:

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
{
    self.edgesForExtendedLayout = UIRectEdgeNone;
}

rootViewController的标签栏我也尝试了以下没有运气:

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
{
    self.tabBarController.edgesForExtendedLayout = UIRectEdgeNone;
}

在我的另一个故事板应用程序中,我能够在底部栏和顶部栏下取消选择。如果没有故事板,我该怎么做才能达到相同的效果?

4

4 回答 4

23

这是从我写的一篇博文中交叉发布的,但这里是 iOS 7 上状态栏、导航栏和容器视图控制器的完整概要:

  1. 没有办法保留 iOS 6 风格的状态栏布局。状态栏将始终与您在 iOS 7 上的应用程序重叠

  2. 不要将状态栏外观与状态栏布局混淆。外观(浅色或默认)不会影响状态栏的布局方式(框架/高度/重叠)。还需要注意的是,系统状态栏不再有任何背景颜色。当 API 引用 UIStatusBarStyleLightContent 时,它们表示清晰背景上的白色文本。UIStatusBarStyleDefault 是清晰背景上的黑色文本。

  3. 状态栏外观由两个互斥的基础路径之一控制:您可以以传统方式以编程方式设置它们,或者 UIKit 将根据 UIViewController 的一些新属性为您更新外观。后一个选项默认开启。检查您应用的 plist 值是否为“基于 ViewController 的状态栏外观”,以查看您使用的是哪一个。如果将此值设置为 YES,则应用程序中的每个顶级视图控制器(标准 UIKit 容器视图控制器除外)都需要覆盖 PreferredStatusBarStyle,返回默认样式或灯光样式。如果将 plist 值编辑为 NO,则可以使用熟悉的 UIApplication 方法管理状态栏外观。

  4. UINavigationController 将根据一组相当奇怪且未记录的约束将其 UINavigationBar 的高度更改为 44 点或 64 点。如果 UINavigationController 检测到其视图框架的顶部与其 UIWindow 的顶部在视觉上是连续的,那么它会绘制高度为 64 磅的导航栏。如果其视图的顶部与 UIWindow 的顶部不连续(即使仅相差一个点),则它以“传统”方式绘制其导航栏,高度为 44 点。这个逻辑由 UINavigationController 执行,即使它是应用程序的视图控制器层次结构中的几个子级。没有办法阻止这种行为。

  5. 如果您提供一个只有 44 点(88 像素)高的自定义导航栏背景图像,并且 UINavigationController 的视图边界与 UIWindow 的边界匹配(如 #4 中所述),则 UINavigationController 将在框架中绘制您的图像(0,20,320 ,44),在您的自定义图像上方留下 20 点不透明的黑色空间。这可能会让您误以为自己是绕过规则 1 的聪明开发人员,但您错了。导航栏仍然是 64 点高。在滑动显示样式视图层次结构中嵌入 UINavigationController 可以使这一点非常清晰。

  6. 当心 UIViewController 的命名混淆的 edgesForExtendedLayout 属性。在大多数情况下,调整 edgeForExtendedLayout 没有任何作用。UIKit 使用此属性的唯一方法是,如果您将视图控制器添加到 UINavigationController,则 UINavigationController 使用 edgesForExtendedLayout 来确定其子视图控制器是否应该在导航栏/状态栏区域下方可见。在 UINavigationController 本身上设置 edgesForExtendedLayout 不会改变 UINavigationController 是否具有 44 点或 64 点高的导航栏区域。有关该逻辑,请参见#4。使用工具栏或 UITabBarController 时,类似的布局逻辑适用于视图的底部。

  7. 如果您要做的只是防止您的自定义子视图控制器在 UINavigationController 内覆盖导航栏,则将 edgesForExtendedLayout 设置为 UIRectEdgeNone(或至少一个不包括 UIRectEdgeTop 的掩码)。在视图控制器的生命周期中尽早设置此值。

  8. UINavigationController 和 UITabBarController 还将尝试在其子视图层次结构中填充表视图和集合视图的 contentInsets。它以类似于#4 中的状态栏逻辑的方式执行此操作。有一种编程方法可以防止这种情况发生,通过将表视图和集合视图的自动调整滚动视图插入设置为否(默认为是)。这给 Whisper 和 Riposte 带来了一些严重的问题,因为我们使用 contentInset 调整来控制表格视图的布局以响应工具栏和键盘的移动。

  9. 重申一下:没有办法回到 iOS 6 风格的状态栏布局逻辑。为了近似这一点,您必须将应用程序的所有视图控制器移动到从屏幕顶部偏移 20 个点的容器视图中,在状态栏后面故意留下黑色视图以模拟旧外观。这是我们最终在 Riposte 和 Whisper 中使用的方法。

  10. Apple 正在努力确保您不会尝试执行 #9。他们希望我们重新设计所有应用程序以覆盖状态栏。然而,出于用户体验和技术原因,有许多令人信服的论点,为什么这并不总是一个好主意。您应该为您的用户做最好的事情,而不是简单地跟随平台的奇思妙想。

于 2013-09-24T13:06:50.577 回答
3

在检查哪个操作系统用户正在使用之后,只需将此行添加到您的 AppDelegate 即可。

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-20);
    self.window.bounds = CGRectMake(0, 20, self.window.frame.size.width, self.window.frame.size.height);
}
于 2013-09-24T12:23:30.420 回答
2

嗨,我希望这会对你有所帮助。此代码适用于我。请将此代码粘贴到您的 ViewDidLoad

    if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;
于 2013-09-24T13:01:15.570 回答
1

对于 IOS7,您可以从顶部离开状态栏高度,这在 IOS6 中是默认设置的。

float SystemVersion=[[[UIDevice currentDevice] systemVersion] floatValue];

if(SystemVersion<7.0f)
{
    //Currently your app is running in IOS6 or older version. So you need not to do anything.  
}
else
{
    // Currently your app is running in IOS7. Do the following.

    CGRect TempRect;
    for(UIView *sub in [[self view] subviews])
    {
        TempRect=[sub frame];
        TempRect.origin.y+=20.0f; //Height of status bar
        [sub setFrame:TempRect];
    }
}
于 2013-09-24T12:39:05.150 回答