在 iOS 7 中,状态栏和导航栏出现在我的视图边界上
Posted
技术标签:
【中文标题】在 iOS 7 中,状态栏和导航栏出现在我的视图边界上【英文标题】:Status bar and navigation bar appear over my view's bounds in iOS 7 【发布时间】:2013-06-12 20:06:41 【问题描述】:我最近下载了Xcode 5 DP 来测试我在 ios 7 中的应用程序。我注意到并确认的第一件事是,我的视图边界并不总是根据状态栏和导航栏调整大小。
在viewDidLayoutSubviews
中,我打印视图的边界:
0, 0, 320, 568
这会导致我的内容显示在导航栏和状态栏下方。
我知道我可以通过获取主屏幕的高度,减去状态栏的高度和导航栏的高度来计算高度,但这似乎是不必要的额外工作。
我该如何解决这个问题?
更新:
我已经找到了解决这个特定问题的方法。将导航栏的 translucent 属性设置为 NO:
self.navigationController.navigationBar.translucent = NO;
这将修复视图在导航栏和状态栏下方的框架。
但是,当您希望导航栏为半透明时,我还没有找到解决方法。例如,在全屏查看照片时,我希望导航栏是半透明的,并且视图要框在它下面。这行得通,但是当我切换显示/隐藏导航栏时,我遇到了更奇怪的结果。第一个子视图(一个 UIScrollView)每次都会改变它的边界 y 原点。
【问题讨论】:
我在 xcode 5 DP 中也遇到了同样的问题 如果您能找到解决方案,请告诉我 在导航栏中查找 tint color 属性,您应该能够将蓝色更改为您想要的任何颜色。 有时我讨厌升级 ios,因为 Apple 从来没有给你机会让你的应用向后兼容。 如果问题与隐藏导航控制器顶部栏后状态栏下的视图有关,我会参考@Stunner ***.com/a/18976660/235206 的答案作为解决方案 【参考方案1】:您可以通过在 iOS7 SDK 中实现一个名为 edgesForExtendedLayout
的新属性来实现这一点。请添加以下代码来实现这一点,
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
您需要在-(void)viewDidLoad
方法中添加上述内容。
iOS 7 对您如何布局和自定义 UI 的外观。视图控制器布局、色调的变化 颜色和字体会影响应用中的所有 UIKit 对象。在 此外,手势识别器 API 的增强功能让您更精细 对手势交互的粒度控制。
使用视图控制器
在 iOS 7 中,视图控制器使用全屏布局。同时, iOS 7 让您可以更精细地控制视图控制器的方式 阐述其观点。特别是全屏布局的概念 已改进为让视图控制器指定每个视图的布局 视野的边缘。
wantsFullScreenLayout
视图控制器属性在 iOS 7. 如果您当前指定wantsFullScreenLayout = NO
,则视图 控制器可能会在意外的屏幕位置显示其内容 当它在 iOS 7 中运行时。要调整视图控制器的视图布局方式,
edgesForExtendedLayoutUIViewController
提供以下属性:extendedLayoutIncludesOpaqueBars
edgesForExtendedLayout
属性使用UIRectEdge
类型, 它指定了矩形的四个边中的每一个,除了 指定无和全部。使用edgesForExtendedLayout
指定哪个 无论条形半透明如何,都应扩展视图的边缘。经过 默认情况下,该属性的值为UIRectEdgeAll
。如果您的设计使用不透明条,请将
自动调整ScrollViewInsetsedgesForExtendedLayout
细化为 还将extendedLayoutIncludesOpaqueBars
属性设置为 否。 (extendedLayoutIncludesOpaqueBars
的默认值为 NO。)如果您不希望滚动视图的内容插入自动进行 调整后,将
topLayoutGuide、bottomLayoutGuideautomaticallyAdjustsScrollViewInsets
设置为NO。 (这automaticallyAdjustsScrollViewInsets
的默认值为 YES。)
topLayoutGuide
和bottomLayoutGuide
属性表示 视图控制器视图中顶部或底部条边的位置。 如果条应该与视图的顶部或底部重叠,您可以使用 Interface Builder 通过创建相对于栏来定位视图 约束到topLayoutGuide
的底部或顶部 底部布局指南。 (如果没有条应该与视图重叠,则底部topLayoutGuide
同视图顶部和顶部bottomLayoutGuide
与视图底部相同。)两者 请求时延迟创建属性。
请参考apple doc
【讨论】:
iOS6下无法编译。我觉得应该写成performselector... 是的,这就是为什么我将选择器检查包含在 if 条件中,if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) 如果我没有导航栏,这将不起作用。在这种情况下,我的视图延伸到状态栏后面.. 我和@VanDuTran 有同样的问题。如果导航栏被隐藏,edgesForExtendedLayout 将无济于事。 它可以工作,但是......不再有半透明效果......我们怎样才能保持半透明效果......【参考方案2】:您不必计算将所有内容向下移动多远,为此有一个内置属性。在 Interface Builder 中,突出显示您的视图控制器,然后导航到属性检查器。在这里,您会在“扩展边缘”一词旁边看到一些复选框。如您所见,在第一个屏幕截图中,默认选择是内容显示在顶部和底部栏下,而不是在不透明栏下,这就是为什么将栏样式设置为不透明对您有用的原因。
正如您在第一个屏幕截图中所看到的,导航栏下方隐藏着两个 UI 元素。 (我在 IB 中启用了线框来说明这一点)这些元素,一个 UIButton 和一个 UISegmentedControl 都将它们的“y”原点设置为零,并且视图控制器设置为允许顶部栏下方的内容。
第二个屏幕截图显示了当您取消选中“顶部栏下方”复选框时会发生什么。如您所见,视图控制器视图已适当向下移动,使其 y 原点位于导航栏的正下方。
这也可以通过使用-[UIViewController edgesForExtendedLayout]
以编程方式完成。这是edgeForExtendedLayout 和UIRectEdge 的类参考链接
[self setEdgesForExtendedLayout:UIRectEdgeNone];
【讨论】:
如何只在 .xib 中查看? 我在视图中添加了一个标签,并按照您的指示进行操作,但这对我不起作用 @bobics XIB 问题的答案是,“你不能。”反正不是通过IB。提交雷达并希望 Apple 最终解决它。 感谢@0x7fffffff,这正是我正在寻找的信息,非常有帮助。【参考方案3】:我以编程方式创建了我的视图,这最终对我有用:
- (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;
Source(在第 39 页底部的 topLayoutGuide 部分)。
【讨论】:
终于找到了一个真正适用于此的答案。干得好! 为了解决隐藏导航栏时视图控制器的视图显示在状态栏下的问题,这是将视图捕捉到状态栏下的代码。 注意:这会将视图的底部推离屏幕。 另外,除非你是为only iOS7 构建的,否则上面的代码会抛出一个错误——topLayoutGuide
is only iOS7.
另请注意,当您的主视图是 UITableView 时,每次滚动都会调用 viewDidLayoutSubviews。您的 UITableView 将按比例缩小,直到其高度为 15 像素。添加一个标志以仅运行此代码一次。 ;)【参考方案4】:
Swift 3 / Swift 4 解决方案也适用于 iOS 10+ 中的 NIB/XIB 文件:
override func viewDidLoad()
super.viewDidLoad()
edgesForExtendedLayout = []
【讨论】:
这对我有帮助...如此简单。谢谢:-) 谢谢,真的很有帮助 这是 10.x Swift 3+ IMO 的最佳解决方案【参考方案5】:如果您希望视图具有半透明导航栏(这很不错),您必须设置 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);
【讨论】:
为什么不能和7.0直接比较 大声笑我明白了:检查添加了次要版本的特定版本不太健壮。但是您正在检查该值是否更大或等于,因此与 7.0 相比在这里就可以了;) @leena - 这是 7.x 及更高版本中的功能 - 所以我检查版本是否为 7 或更高版本并跳过检查中的次要修订。 Tabbar 后面显示的 tableView 出现问题。这使得我的表格的最后一行永远不会在 Tabbar 上方滚动。我这样修复它: myTableView.contentInset = UIEdgeInsetsMake(0, 0.0, TabbarHeight, 0)contentInset
是 UIScrollView
的属性。如果我的主视图不是UIScrollView
的子类怎么办。那我该如何解决重叠问题呢?【参考方案6】:
edgesForExtendedLayout
适用于 iOS 7。但是,如果您跨 iOS 7 SDK 构建应用程序并将其部署到 iOS 6 中,导航栏将显示为半透明,并且视图位于其下方。因此,要为 iOS 7 和 iOS 6 修复它,请执行以下操作:
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone; // iOS 7 specific
【讨论】:
【参考方案7】:在您的应用程序 plist 文件中添加一行,将其命名为“基于控制器的状态栏外观”并将其设置为 NO。
【讨论】:
【参考方案8】:最简单的技巧是打开NIB文件并执行以下两个简单步骤:
-
只需切换它并将其设置为您喜欢的:
-
选择那些你想下移的 UIView's/UIIMageView's/...。就我而言,只有徽标重叠,我将增量设置为 +15; (如果您在第 1 步中选择了 iOS 7,则为 -15)
以及结果:
【讨论】:
它有效,但这看起来是一个难以维护的解决方案。最好只是解决问题而不是修补它。 最好以编程方式对所有视图的子视图执行此操作,因为如果应用于主视图则不起作用【参考方案9】:快速解决方案:
override func viewWillAppear(animated: Bool)
super.viewWillAppear(animated)
self.edgesForExtendedLayout = UIRectEdge.None
【讨论】:
现在是 edgesForExtendedLayout = [] 因为这是一个公开的答案,我们不应该忘记致电:super.viewWillAppear(animated)
【参考方案10】:
我想扩展 Stunner 的答案,并添加一个 if
语句来检查它是否是 iOS-7,因为当我在 iOS 6 上测试它时,我的应用程序会崩溃。
添加将是:
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
所以我建议将此方法添加到您的 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;
【讨论】:
【参考方案11】:斯威夫特 3
override func viewWillAppear(_ animated: Bool)
self.edgesForExtendedLayout = []
【讨论】:
【参考方案12】:我有一个场景,我使用 Apple 编写的 BannerViewController 来显示我的广告和嵌入在 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;
现在广告可以正确显示在视图的底部,而不是被导航栏覆盖,并且顶部的内容不会被截断。
【讨论】:
【参考方案13】:只要在视图中设置如下代码就会出现。
if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7)
self.edgesForExtendedLayout = UIRectEdgeNone;
【讨论】:
这是在我的情况下唯一有效的方法。【参考方案14】:像这样对顶部布局进行约束
【讨论】:
【参考方案15】:Swift 4.2 - Xcode 10.0 - iOS 12.0:
if #available(iOS 11.0, *) else
self.edgesForExtendedLayout = []
self.navigationController?.view.backgroundColor = .white
【讨论】:
【参考方案16】:对我来说,最简单的解决方案是在 plist 中添加两个键
【讨论】:
+1,我有“状态栏最初隐藏”=YES,但是当添加“查看基于控制器的状态栏外观”=NO 时,我摆脱了状态栏。【参考方案17】:将下拉列表中的“基于视图控制器的状态栏外观”键添加为info.plist
中的一行。像这样:
【讨论】:
很有趣。它对我的 cocos2d 项目有所帮助。当我切换此选项时,我可以看到顶部状态栏完全消失或出现。【参考方案18】:我的 iPad 应用程序(armv7、armv7s、amr64)也遇到了同样的问题,只是通过呈现另一个 UIViewController 并在解除它们后进入状态栏下的导航栏... 我花了很多时间来寻找任何解决方案。我正在使用故事板和 UIViewController 的 InterfaceBuilder,这使得我从 FullScreen -> Current Context 设置 Presentation 并解决了这个问题。它仅适用于我的应用程序,适用于 iPads => iOS8.0(使用 iOS8.1 进行测试),并且适用于 iOS 7.1 的 iPad 不起作用!!
【讨论】:
就我而言,我的主视图与我的 tabBar 重叠,我不知道为什么。事实证明,Extend Edges > Under Bottom Bars 已被选中。真的很难注意到它,因为我的应用程序的背景是白色的,它只会在我的 tabBar 上产生一定程度的不透明度。谢谢!【参考方案19】:在 iOS 7 中隐藏状态栏的步骤:
1.转到您的应用程序 info.plist 文件。
2.And Set,查看基于控制器的状态栏外观:Boolean NO
希望我解决了状态栏问题.....
【讨论】:
【参考方案20】:在我的情况下 loadView() 被中断 这段代码: self.edgesForExtendedLayout = UIRectEdgeNone
但删除 loadView() 后一切正常
【讨论】:
以上是关于在 iOS 7 中,状态栏和导航栏出现在我的视图边界上的主要内容,如果未能解决你的问题,请参考以下文章