视图不会从iOS7中状态栏的底部开始

时间:2013-09-24 12:13:19

标签: iphone ios objective-c ios7

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

enter image description here

在iOS6中,它从状态栏下方的正确位置开始。请注意,我是以编程方式创建此UI,而不是从故事板创建。

我找到了以下解决方案并将其放在我的视图控制器中,但它无法正常工作:

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

我的rootViewController是标签栏,我也尝试了以下运气:

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

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

4 个答案:

答案 0 :(得分:23)

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

  1. 无法保留iOS 6样式状态栏布局。状态栏将始终与iOS 7上的应用程序重叠

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

  3. 状态栏外观是根据两个互斥的基本路径之一控制的:您可以以传统方式以编程方式设置它们,或者UIKit将根据UIViewController的一些新属性为您更新外观。后一个选项默认启用。检查应用程序的“基于ViewController的状态栏外观”的plist值,看看你正在使用哪一个。如果将此值设置为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属性。调整edgesForExtendedLayout在大多数情况下不执行任何操作。 UIKit使用此属性的唯一方法是,如果将视图控制器添加到UINavigationController,则UINavigationController使用edgesForExtendedLayout来确定其子视图控制器是否应在导航栏/状态栏区域下可见。在UINavigationController上设置edgesForExtendedLayout本身不会改变UINavigationController是否具有44或64点高导航栏区域。有关该逻辑,请参阅#4。使用工具栏或UITabBarController时,类似的布局逻辑适用于视图的底部。

  7. 如果你想要做的就是阻止你的自定义子视图控制器在UINavigationController内置于导航栏下面,然后将edgesForExtendedLayout设置为UIRectEdgeNone(或者至少是一个排除UIRectEdgeTop的掩码)。在视图控制器的生命周期中尽早设置此值。

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

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

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

答案 1 :(得分:3)

在检查了哪个OS用户正在使用之后,只需将此行添加到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);
}

答案 2 :(得分:2)

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

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

答案 3 :(得分: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];
    }
}