状态栏和导航栏显示在我的视图的边界在iOS 7中
我最近下载了Xcode 5 DP来在iOS 7中testing我的应用程序。我注意到并确认的第一件事是我的视图的边界并不总是调整到状态栏和导航栏的大小。
在viewDidLayoutSubviews
,我打印视图的边界:
{{0,0},{320,568}}
这导致我的内容出现在导航栏和状态栏的下面。
我知道我可以通过获得主屏幕的高度,减去状态栏的高度和导航栏的高度来解释高度,但是这似乎是不必要的额外工作。
我该如何解决这个问题?
更新:
我find了解决这个特定问题的方法。 将导航栏的半透明属性设置为NO:
self.navigationController.navigationBar.translucent = NO;
这将修复导航栏和状态栏下面的视图。
但是,我还没有find一个解决scheme,当你想导航栏是半透明的。 例如,全屏查看照片,我希望导航栏是半透明的,并且要将视图框在其下面。 这是有效的,但是当我切换显示/隐藏导航栏,我遇到了更奇怪的结果。 第一个子视图(UIScrollView)每次都会更改原点的边界。
您可以通过在iOS7 SDK中实现一个名为edgesForExtendedLayout
的新属性来实现此目的。 请添加下面的代码来实现这一点,
if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone;
你需要在你的-(void)viewDidLoad
方法中添加上面的代码。
iOS 7对布局和自定义UI的外观带来了一些变化。 视图控制器布局,色调和字体的变化会影响应用程序中的所有UIKit对象。 另外,手势识别器API的增强function可以更好地控制手势交互。
使用视图控制器
在iOS 7中,视图控制器使用全屏布局。 与此同时,iOS 7为您提供了对视图控制器布局视图的更精确的控制。 特别是,全屏布局的概念已经完善,让视图控制器指定其视图的每个边缘的布局。
在iOS 7中不推荐使用
wantsFullScreenLayout
视图控制器属性。如果当前指定wantsFullScreenLayout = NO
,则视图控制器可能会在iOS 7中运行时在意外的屏幕位置显示其内容。要调整视图控制器布局视图的方式,
UIViewController
提供了以下属性:
- edgesForExtendedLayout
edgesForExtendedLayout
属性使用UIRectEdge
types,除了指定none和all以外,还指定了每个矩形的四条边。 使用edgesForExtendedLayout
来指定应该扩展视图的哪些边,而不考虑bar半透明度。 默认情况下,这个属性的值是UIRectEdgeAll
。
- extendedLayoutIncludesOpaqueBars
如果您的devise使用了不透明的酒吧,
edgesForExtendedLayout
通过将extendedLayoutIncludesOpaqueBars
属性设置为NO来优化edgesForExtendedLayout
。 (extendedLayoutIncludesOpaqueBars
的默认值是NO 。)
- automaticallyAdjustsScrollViewInsets
如果您不希望自动调整滚动视图的内容插图,请将
automaticallyAdjustsScrollViewInsets
调整滚动视图插入设置为否 。 (automaticallyAdjustsScrollViewInsets
的默认值为YES 。)
- topLayoutGuide,bottomLayoutGuide
topLayoutGuide
和bottomLayoutGuide
属性指示视图控制器视图中顶部或底部条边的位置。 如果条纹应该与视图的顶部或底部重叠,则可以使用Interface Builder通过在topLayoutGuide
的底部或topLayoutGuide
的顶部创build约束来定位相对于条的视图。 (如果没有条应该与视图重叠,则topLayoutGuide
的底部与视图的顶部相同,而topLayoutGuide
的顶部与视图的底部相同。)这两个属性都是在请求时延迟创build的。
请参阅苹果文档
你不需要计算转移的距离有多远,这里有一个属性的构build。 在Interface Builder中,突出显示您的视图控制器,然后导航到属性检查器。 在这里,您会看到“Extend Edges”旁边的一些checkbox。 正如你所看到的,在第一个屏幕截图中,默认的select是内容出现在顶部和底部的小节中,而不是在不透明的小节下面,这就是为什么设置小节样式不是半透明的。
正如您在第一个屏幕截图中所看到的那样,在导航栏下面隐藏了两个UI元素。 (我已经在IB中启用线框图来说明这一点)这些元素,UIButton和UISegmentedControl都将其“y”原点设置为零,并且视图控制器被设置为允许内容在顶部条之下。
第二个屏幕截图显示当您取消选中“Under Top Bars”checkbox时发生的情况。 正如你所看到的,视图控制器视图已经被适当地向下移动,其y原点恰好在导航栏的下面。
这也可以通过使用-[UIViewController edgesForExtendedLayout]
以编程方式完成。 这里是edgeForExtendedLayout和UIRectEdge的类参考的链接
[self setEdgesForExtendedLayout:UIRectEdgeNone];
我以编程的方式创build了我的视图,并最终为我工作:
- (void) viewDidLayoutSubviews { // only works for iOS 7+ if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { CGRect viewBounds = self.view.bounds; CGFloat topBarOffset = self.topLayoutGuide.length; // snaps the view under the status bar (iOS 6 style) viewBounds.origin.y = topBarOffset * -1; // shrink the bounds of your view to compensate for the offset viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1); self.view.bounds = viewBounds; } }
来源 (在第39页底部的topLayoutGuide部分)。
Swift 3解决scheme也适用于iOS 10中的NIB / XIB文件:
override func viewDidLoad() { super.viewDidLoad() edgesForExtendedLayout = [] }
如果你想要视图有半透明的导航栏(这是一种很好),你必须设置一个contentInset或类似的。
下面是我如何做到这一点:
// Check if we are running on ios7 if([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."][0] intValue] >= 7) { CGRect statusBarViewRect = [[UIApplication sharedApplication] statusBarFrame]; float heightPadding = statusBarViewRect.size.height+self.navigationController.navigationBar.frame.size.height; myContentView.contentInset = UIEdgeInsetsMake(heightPadding, 0.0, 0.0, 0.0); }
edgesForExtendedLayout
为iOS 7操作。但是,如果您在iOS 7 SDK中构build应用程序并在iOS 6中部署应用程序,则导航栏将显示为半透明,视图将位于其下方。 所以,要解决它的iOS 7以及iOS 6这样做:
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque; if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone; // iOS 7 specific
在您的应用程序plist文件中添加一行,将其称为“查看基于控制器的状态栏外观”,并将其设置为NO 。
最简单的窍门是打开NIB文件并执行以下两个简单步骤:
- 只需切换,并将其设置为您喜欢的那个:
- select你想要向下移动的UIView / UIIMageView的/ …。 在我的情况下,只有标志重叠,我已经设置三angular洲+15; (如果您在步骤1中select了iOS 7,则为-15)
结果是 :
我想扩大Stunner的答案,并添加if
语句来检查它是否是iOS-7,因为当我在iOS 6上testing它时,我的应用程序会崩溃。
增加将增加:
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
所以我build议把这个方法添加到你的MyViewControler.m
文件中:
- (void) viewDidLayoutSubviews { if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { CGRect viewBounds = self.view.bounds; CGFloat topBarOffset = self.topLayoutGuide.length; viewBounds.origin.y = topBarOffset * -1; self.view.bounds = viewBounds; } }
Swift解决scheme:
override func viewWillAppear(animated: Bool) { self.edgesForExtendedLayout = UIRectEdge.None }
我有一个场景,我使用由Apple写的BannerViewController来显示我的广告和embedded在BannerViewController中的ScrollViewController。
为了防止导航栏隐藏我的内容,我必须做两个更改。
1)修改BannerViewController.m
- (void)viewDidLoad { [super viewDidLoad]; float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (systemVersion >= 7.0) { self.edgesForExtendedLayout = UIRectEdgeNone; } }
2)修改我的ScrollViewContoller
- (void)viewDidLoad { [super viewDidLoad]; float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (systemVersion >= 7.0) { self.edgesForExtendedLayout = UIRectEdgeBottom; } }
现在广告正确显示在视图的底部,而不是被导航栏覆盖,而顶部的内容不会被截断。
Swift 3
override func viewWillAppear(_ animated: Bool) { self.edgesForExtendedLayout = [] }
对我来说,最简单的解决方法是在plist中添加两个键
在下拉列表中添加“View Controller-based status bar appearance”这个关键字作为info.plist
的一行。 像这样的东西:
我只有通过展示另一个UIViewController来解决iPad和iPad的问题(armv7,armv7s,amr64),然后closures状态栏下的导航栏,我花了很多时间find解决scheme。 我正在使用故事板和InterfaceBuilder中的UIViewController,这使得我从全屏 – >当前上下文设置演示可怕,它解决了这个问题。 它在我的应用程序只适用于iPad => iOS8.0(testing与iOS8.1)和iPad的iOS 7.1不工作!
只要在视图中设置下面的代码就会出现。
if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) { self.edgesForExtendedLayout = UIRectEdgeNone; }
像这样对顶部布局做一个约束
步骤隐藏iOS 7中的状态栏:
1.转到您的应用程序info.plist文件。
2.设置,查看基于控制器的状态栏外观:Boolean NO
希望我解决了状态栏问题…..
在我的情况下loadView()中断
这个代码:self.edgesForExtendedLayout = UIRectEdgeNone
但删除loadView()后,一切正常