iOS7 – 在状态栏下查看 – edgesForExtendedLayout不工作

我有一个去年build立的项目,它使用XIB,没有故事板。 XIB不使用自动布局,但他们使用一些自动调整。 在使用iOS7运行时,我遇到了一个问题,其中所有视图都隐藏在状态栏下。 我完全理解这是iOS7的一个新function,可以预料到这一点。 但是,所有的解决scheme,以解决它不这样做是行不通的。 我在视图的顶部有一个图像,总是在状态栏下显示,而且我没有使用导航栏或类似的东西。

我已经尝试更新XIB中的Y-deltas(它们对视图没有影响),我试图设置edgesForExtendedLayoutUIRectEdgeNone (什么也不做),还有很多其他的东西。 每次,状态栏都会显示下面的视图,无论我做什么……除非我手动向下移动XIB中的视图以允许状态栏的空间(但是解决scheme不起作用,因为它当然,在iOS6中看起来不正确)。

奇怪的是,即使我尝试了一系列的代码来进行视图切换,它也不起作用(如下所示):

 self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+20, self.view.frame.size.width, self.view.frame.size.height); 

..不是我会用这样的解决scheme,但它是不正常的,这是行不通的(唯一一次我通常看到,不工作是如果自动布局是在位,这是不是在这种情况下)。

这是一个devise要求,状态栏显示,我只是为什么我不能将视图设置为在iOS7的状态栏下难住。 我已经阅读了关于这个主题的每一个Stack Overflowpost,以及苹果的转换/指南。 我再一次重申,我完全理解它应该如何运作,以及预期的解决scheme应该如何,但似乎没有任何一个工作在这个特定的项目上。

我是一个经验丰富的iOS开发人员,但是这个项目是由另外一个团队构build的,所以我不知道在XIB文件,plist或代码中是否隐藏了一些可能会超出上述设置的东西。 请让我知道,如果有什么可以看看这个,或更多的信息,我可以提供。

提前致谢!

如果在Interface Builder中设置iOS 6/7增量值,请记住在Interface Builder文档中将“View as”设置为“iOS 6”,因为它是要复制的iOS 6版式。 只有在iOS 7上才能使用deltas来将状态栏下的内容推送出去。 如果您将“查看为”设置为iOS 7(默认设置),那么增量variables将为您提供iOS 6上的iOS 7外观。

但是,如果您基于视图框架以编程方式重新定位视图或调整视图的大小,那么delta不会帮助您,因为该框架不会计算增量。

我find的最佳解决scheme是在主XIB上启用“自动布局”,然后在顶部/内容视图上设置顶部空间约束,以遵循“顶部布局指南”,而不是使用增量。 本指南是在iOS 7中引入的,代表状态栏下方的位置。 不幸的是,在不使用Storyboard的情况下,Interface Builder中不提供该指南,但可以通过编程方式进行添加。

我所做的是在顶层空间约束添加到超级视图,而不是在Interface Builder中,并在代码中创build了一个sockets。 然后,在viewDidLoad中,如果topLayoutGuide可用(iOS 7+),请使用顶部版式指南replace此插件中的约束。

 if ([self respondsToSelector:@selector(topLayoutGuide)]) { [self.view removeConstraint:self.containerTopSpaceConstraint]; self.containerTopSpaceConstraint = [NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; [self.view addConstraint:self.containerTopSpaceConstraint]; [self.view setNeedsUpdateConstraints]; [self.view layoutIfNeeded]; } 

作为参考,下面的解决scheme,当我把它应用到我的ViewControllers工作。 然而,这不是理想的,有点哈克。 如果这是我能采取的唯一方法,那就这样吧。

 float systemVersion=[[[UIDevice currentDevice] systemVersion] floatValue]; if(systemVersion>=7.0f) { CGRect tempRect; for(UIView *sub in [[self view] subviews]) { tempRect = [sub frame]; tempRect.origin.y += 20.0f; //Height of status bar [sub setFrame:tempRect]; } } 

苹果推动你使用自动布局来实现这一点。 您需要在视图的顶部子视图中为“顶部布局指南”设置一个约束。

有关示例,请参阅此文档:

https://developer.apple.com/library/ios/qa/qa1797/_index.html

要做到这一点没有XIB,你需要以编程方式添加约束。 苹果的文档给出了一个很好的例子,我在下面总结。

topLayoutGuide是视图控制器上的一个属性,你可以在你的variables绑定字典中使用它。 然后你像正常一样设置你的约束:

 id topGuide = [myViewController topLayoutGuide]; NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(button, topGuide); NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[topGuide]-20-[button]" options:0 metrics:nil views:viewsDictionary]; 

这个文档可以在UIViewController类的引用中find 。

1)最简单的解决scheme,如果你不介意有一个不透明的导航栏:

 self.navigationController.navigationBar.translucent = NO; 

2)svguerin3的答案不能在一般情况下工作。 例如,如果其中一个子视图使用自动resize挂钩在其容器的底部,那么它的新位置将是错误的。 在最坏的情况下它可能会熄灭。

 - (void)viewDidAppear:(BOOL)animated { [self.view setFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height)]; // OR self.view.transform = CGAffineTransformMakeTranslation(0, 20); } 

你有没有尝试查看您的XIB作为源和删除任何包含edgesforextendedlayout?

我们不得不在故事板的场景中删除这条线,因为我们的故事板的场景的主视图由XIB表示

发生在我们身上的是,在某些场景中,现场主视图的XIB内容被状态栏和导航栏的高度所压低。

移除该行允许显示XIB,就好像它们的顶部始于其故事板场景的同一顶部。

可悲的是,我们不知道是什么触发了这个,但是当在XIB的主视图中改变内容的顺序时,我看到它发生,所以UITextView首先出现。 在这个事件被触发之后重新排列项目顺序对消除这种不需要的行为没有影响。

希望这有助于任何人遇到这种types的问题。

如果您正在使用故事板,则在设置视图的顶部布局之后,可以取消选中“属性”检查器中的“不透明条”

故事板