转自:http://stackoverflow.com/questions/17074365/status-bar-and-navigation-bar-appear-over-my-views-bounds-in-ios-7

Question:

I recently downloaded Xcode  DP to test my apps in iOS . The first thing I noticed and confirmed is that my view's bounds is not always resized to account for the status bar and navigation bar.

In viewDidLayoutSubviews, I print the view's bounds:

{{, }, {, }}

This results in my content appearing below the navigation bar and status bar.

I know I could account for the height myself by getting the main screen's height, subtracting the status bar's height and navigation bar's height, but that seems like unnecessary extra work.

How can I fix this issue?

Update:

I've found a solution for this specific problem. Set the navigation bar's translucent property to NO:

self.navigationController.navigationBar.translucent = NO;
This will fix the view from being framed underneath the navigation bar and status bar. However, I have not found a fix for the case when you want the navigation bar to be translucent. For instance, viewing a photo full screen, I wish to have the navigation bar translucent, and the view to be framed underneath it. That works, but when I toggle showing/hiding the navigation bar, I've experienced even stranger results. The first subview (a UIScrollView) gets its bounds y origin changed every time.

You can achieve this by implementing a new property called edgesForExtendedLayout in iOS7 SDK. Please add the following code to achieve this,

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

You need to add the above in your -(void)viewDidLoad method.

iOS 7 brings several changes to how you layout and customize the appearance of your UI. The changes in view-controller layout, tint color, and font affect all the UIKit objects in your app. In addition, enhancements to gesture recognizer APIs give you finer grained control over gesture interactions.

Using View Controllers

In iOS 7, view controllers use full-screen layout. At the same time, iOS 7 gives you more granular control over the way a view controller lays out its views. In particular, the concept of full-screen layout has been refined to let a view controller specify the layout of each edge of its view.

The wantsFullScreenLayout view controller property is deprecated in iOS 7. If you currently specify wantsFullScreenLayout = NO, the view controller may display its content at an unexpected screen location when it runs in iOS 7.

To adjust how a view controller lays out its views, UIViewController provides the following properties:

  • edgesForExtendedLayout

The edgesForExtendedLayout property uses the UIRectEdge type, which specifies each of a rectangle’s four edges, in addition to specifying none and all. Use edgesForExtendedLayout to specify which edges of a view should be extended, regardless of bar translucency. By default, the value of this property is UIRectEdgeAll.

  • extendedLayoutIncludesOpaqueBars

If your design uses opaque bars, refine edgesForExtendedLayout by also setting the extendedLayoutIncludesOpaqueBars property to NO. (The default value of extendedLayoutIncludesOpaqueBars is NO.)

  • automaticallyAdjustsScrollViewInsets

If you don’t want a scroll view’s content insets to be automatically adjusted, set automaticallyAdjustsScrollViewInsets to NO. (The default value of automaticallyAdjustsScrollViewInsets is YES.)

  • topLayoutGuide, bottomLayoutGuide

The topLayoutGuide and bottomLayoutGuide properties indicate the location of the top or bottom bar edges in a view controller’s view. If bars should overlap the top or bottom of a view, you can use Interface Builder to position the view relative to the bar by creating constraints to the bottom of topLayoutGuide or to the top of bottomLayoutGuide. (If no bars should overlap the view, the bottom of topLayoutGuide is the same as the top of the view and the top of bottomLayoutGuide is the same as the bottom of the view.) Both properties are lazily created when requested.

Please refer, apple doc

answered Sep 13 '13 at 11:52
Nandha
3,9161819
 
2  
It will not compile under iOS6. I think it should be written as performselector... –  Shmidt Sep 16 '13 at 9:38
8  
Yes, Thats why I have included the selector check with if condition, if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) –  Nandha Sep 16 '13 at 11:40
12  
This would not work if I have no navigation bar. In that case, my view is extends behind the status bar.. – Van Du Tran Sep 24 '13 at 14:51
4  
I have the same problem as @VanDuTran. edgesForExtendedLayout does not help if the navigation bar is hidden. –  fishinear Sep 24 '13 at 16:23
4  
it works but ... there is no longer translucent effect... how can we preserve translucent effect as well... – Red Devil Oct 16 '13 at 19:11
 

You don't have to calculate how far to shift everything down, there's a build in property for this. In Interface Builder, highlight your view controller, and then navigate to the attributes inspector. Here you'll see some check boxes next to the words "Extend Edges". As you can see, in the first screenshot, the default selection is for content to appear under top and bottom bars, but not under opaque bars, which is why setting the bar style to not translucent worked for you.

As you can somewhat see in the first screenshot, there are two UI elements hiding below the navigation bar. (I've enabled wireframes in IB to illustrate this) These elements, a UIButton and a UISegmentedControl both have their "y" origin set to zero, and the view controller is set to allow content below the top bar.

This second screenshot shows what happens when you deselect the "Under Top Bars" check box. As you can see, the view controllers view has been shifted down appropriately for its y origin to be right underneath the navigation bar.

This can also be accomplished programmatically through the usage of -[UIViewController edgesForExtendedLayout]. Here's a link to the class reference for edgeForExtendedLayout, and forUIRectEdge

[self setEdgesForExtendedLayout:UIRectEdgeNone];
answered Sep 13 '13 at 11:56
0x7fffffff
41.6k1587139
 
7  
How do I do the same for just view in a .xib? –  bobics Sep 13 '13 at 21:34
2  
I added one label on view and I followed your instruction but this is not working for me –  user1685099 Sep 20 '13 at 8:08
2  
@bobics The answer to the XIB question is, "You can't." Not through IB anyway. File a radar and hope Apple eventually addresses it. –  Michael G. Emmons Oct 10 '13 at 17:51
    
Thanks @0x7fffffff, This was just the info I was looking for and was very helpful. –  campo Oct 10 at 21:06

I created my view programmatically and this ended up working for me:

- (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 (in topLayoutGuide section at bottom of pg.39).

answered Sep 24 '13 at 8:35
Stunner
3,63233171
 
    
Finally found an answer that actually works for this. Good work! –  StuartM Sep 28 '13 at 0:26
1  
To solve the problem whereby the view controller's view shows up under the status bar when the navigation bar is hidden, this is the code which snaps the view under the status bar. –  MiKL Oct 1 '13 at 14:52
    
Note: this will push the bottom of your view off the screen. –  Michael G. Emmons Oct 10 '13 at 17:08
1  
Also, unless you are building for only iOS7, the above code will throw an error - topLayoutGuide is iOS7 only. –  Michael G. Emmons Oct 10 '13 at 17:11
1  
Also note that when your main view is a UITableView the viewDidLayoutSubviews will get called on each scroll. Your UITableView will be scaled down until its height is 15px. Add a flag to only run this code once. ;)–  Thomas Johannesmeyer Nov 21 '13 at 13:14

If you want the view to have the translucent nav bar (which is kind of nice) you have to setup a contentInset or similar.

Here is how I do it:

// 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);
}
answered Sep 13 '13 at 9:16
Magnus
1,5251225
 
    
what is the requirement to split 7.0 into 7 and 0 ??? @Magnus –  Leena Sep 16 '13 at 9:57
2  
why can't you directly compare it with 7.0 –  Leena Sep 17 '13 at 5:03
    
lol I get it: checking against a specific version with minor added is less robust. But you are checking if the value is BIGGER or equal to so comparing to 7.0 would do just fine here ;) –  EeKay Sep 18 '13 at 6:36
1  
@leena - This is features in 7.x and later - so I check if the version is 7 or greater and skip the minor revisions in the check. –  Magnus Sep 24 '13 at 8:14
1  
I Had an issue with my tableView beeing displayed behind my Tabbar. Which made the last row of my table never to scroll above the Tabbar. I fixed it like that:                                                      myTableView.contentInset =  UIEdgeInsetsMake(0, 0.0, TabbarHeight, 0) –  James Laurenstin Oct 22 '13 at 15:49 

edgesForExtendedLayout does the trick for iOS 7. However, if you build the app across iOS 7 SDK and deploy it in iOS 6, the navigation bar appears translucent and the views go beneath it. So, to fix it for both iOS 7 as well as for iOS 6 do this:

self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone; // iOS 7 specific
answered Sep 21 '13 at 5:18
Raj
3,09673465
 

In your apps plist file add a row, call it "View controller-based status bar appearance" and set it to NO.

answered Sep 19 '13 at 13:45
Idan
4,55632551
 
1  
Works for me, thanks! –  Jim True Oct 23 '13 at 14:30

The simplest trick is to open the NIB file and do these two simple steps:

  1. Just toggle that and set it to the one you prefer:

  1. Select those UIView's/UIIMageView's/... that you want to be moved down. In my case only the logo was overlapped an I've set the delta to +15; (OR -15 if you chose iOS 7 in step 1)

And the result:

 

answered Sep 20 '13 at 10:27
Riskov
19117
 
4  
It works, but this look like a hard to maintain solution. It would be best to just fix the problem instead of patching it. –  NLemay Sep 20 '13 at 21:31
    
it would be best to do it programmatically for all view's subviews because it doesn't work if applied to main view –  wildmonkey Oct 23 '13 at 15:50

I would like to expand on Stunner's answer, and add an if statement to check if it is iOS-7, because when I tested it on iOS 6 my app would crash.

The addition would be adding:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

So I would suggest adding this method to your MyViewControler.m file:

- (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;
}
}
answered Oct 1 '13 at 15:36
 

I have a scenario where I use the BannerViewController written by Apple to display my ads and a ScrollViewController embedded in the BannerViewController.

To prevent the navigation bar from hiding my content, I had to make two changes.

1) Modify BannerViewController.m

- (void)viewDidLoad
{
[super viewDidLoad];
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersion >= 7.0) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
}

2) Modify my ScrollViewContoller

- (void)viewDidLoad
{
[super viewDidLoad];
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersion >= 7.0) {
self.edgesForExtendedLayout = UIRectEdgeBottom;
}
}

Now the ads show up correctly at the bottom of the view instead of being covered by the Navigation bar and the content on the top is not cut off.

answered Oct 21 '13 at 16:35
 

To me, the simplest solution is to add two keys into the plist

answered Oct 3 '13 at 10:28
giuseppe
1,448723
 
    
+1, I had the "Status bar initially hidden"=YES, but when adding "View controller-based status bar appearance"=NO I got rid of the status bar. –  Jonas Byström Oct 28 '13 at 22:32

Add the key "View Controller-based status bar appearance" from the dropdownlist as a row in info.plist. Something like this:

answered Sep 23 '13 at 21:17
N.Ramos
591416
 
3  
Does not help... –  giuseppe Oct 3 '13 at 9:38
    
interesting.it helped on my cocos2d projects.as I toggle this option I can see the top status bar is completely has gone or appear. –  N.Ramos Oct 19 '13 at 5:06 

Steps For Hide the status bar in iOS 7:

1.Go to your application info.plist file.

2.And Set, View controller-based status bar appearance : Boolean NO

Hope i solved the status bar issue.....

Status bar and navigation bar appear over my view's bounds in iOS 7的更多相关文章

  1. 与Status Bar和Navigation Bar相关的一些东西

    Android Navigation Bar Status Bar   与StatusBar和NavigationBar相关的东西有两种,一是控制它们的显示与隐藏,二是控制它们的透明与否及背景. 在2 ...

  2. Navigation bar 的注意事项

    Navigation bar 的注意事项 Bar button item 使用 button 作为 custom view,初始化 isEnabled 为 false,注意顺序 需要设置 bar bu ...

  3. Customizing Navigation Bar and Status Bar

    Like many of you, I have been very busy upgrading my apps to make them fit for iOS 7. The latest ver ...

  4. [Android] 获取系统顶部状态栏(Status Bar)与底部导航栏(Navigation Bar)的高度

    Android一些设备都有上下两条bar,我们可以获取这些bar的信息.下面放上获取高度的代码.代码注释和其他方法有空再放. 原文地址请保留http://www.cnblogs.com/rossone ...

  5. [工作积累] Android: Hide Navigation bar 隐藏导航条

    https://developer.android.com/training/system-ui/navigation.html View decorView = getWindow().getDec ...

  6. Android hide Navigation bar

    最近一个app需要隐藏Navigation bar导航栏. 参考文档 http://blog.csdn.net/zwlove5280/article/details/52823128 http://j ...

  7. IOS7 状态栏和 Navigation Bar重叠的问题解决

    一 Status bar重叠问题: 方法一:隐藏Status bar   在plist里面增加2个变量  Status bar is initially hidden  -> YES   Vie ...

  8. android隐藏底部虚拟键Navigation Bar实现全屏

    隐藏底部虚拟键Navigation Bar实现全屏有两种情况 第一种:始终隐藏,触摸屏幕时也不出现 解决办法:同时设置以下两个参数 View.SYSTEM_UI_FLAG_HIDE_NAVIGATIO ...

  9. 非常不错的Navigation Bar效果

    非常不错的Navigation Bar效果,该源码转载于源码天堂的,大家可以了解一下吧,多视图应用程序中,我们常常使用到自定义UINavigationBar来完成导航条的设置. 源码我就不上传了,大家 ...

随机推荐

  1. 〖Linux〗noip免费域名申请,及更新域名的API

    1. 登录 http://www.noip.com2. 选择 Hosts/Redirects -- Add A Host3. 填写 期望的域名即可(如下图) 4. 更新域名的API: wget -q ...

  2. DATEDIF函数

    DATEDIF(start_date,end_date,unit) DATEDIF函数是Excel隐藏函数,在帮助和插入公式里面没有. 返回两个日期之间的年\月\日间隔数.常使用DATEDIF函数计算 ...

  3. Jmeter-maven-plugin高级配置之选择测试脚本(转)

    Posted on 2014 年 6 月 6 日 在pom.xml文件中可以指定运行哪些jmx脚本. 运行所有的测试脚本 Jmeter默认运行${project.base.directory}/src ...

  4. C#并行编程-PLINQ:声明式数据并行-转载

    C#并行编程-PLINQ:声明式数据并行   目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C#并行编程-线程同步原语 C#并行编程-P ...

  5. 使用maven-assembly-plugin打包zipproject

    使用Maven对Web项目进行打包.默觉得war包.但有些时候.总是希望打成zip包(亦或其它压缩包,类似tomcat的那种文件夹结构,直接运行bin/startup.sh就能够),maven-war ...

  6. 无限极分类php实现—查子孙树、家谱树

    1.本文更新日期:2018/05/20 , 亲测可用,在原有基础上进行增强和 详细化 . 2.面包屑导航 和 子孙树 效果图如下: 3.代码: <?php // 无限级分类中,查家谱树(面包屑导 ...

  7. 【CAS单点登录视频教程】 第02集 -- 安装CAS

    目录 ----------------------------------------- [CAS单点登录视频教程] 第06集[完] -- Cas认证 学习 票据认证FormsAuthenticati ...

  8. CentOS下nodejs最简单的安装方法

    1. 下载编译好的文件 我的系统是centos7,进入要存放下载资源的目录,个人建议存放在/usr/local/src/目录下.然后执行安装命令: wget http://nodejs.org/dis ...

  9. MATLAB 不能保存变量问题及解决办法

    在使用matlab保存结构体.元胞数组等等的变量时,matlab总是提示 警告: 未保存变量 'session'.对于大于 2GB 的变量,请使用 MAT 文件版本 7.3 或更高版本.  问题如下: ...

  10. 优化 App 的启动时间

    这是一篇 WWDC 2016 Session 406 的学习笔记,从原理到实践讲述了如何优化 App 的启动时间. App 运行理论 main() 执行前发生的事 Mach-O 格式 虚拟内存基础 M ...