Status bar and navigation bar appear over my view's bounds in iOS 7


186down votefavorite

122

I recently downloaded Xcode 5 DP to test my apps in iOS 7. 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:

{{0, 0}, {320, 568}}

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.

Has anyone else experienced 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.

ios ios7


share|edit|flag

edited Jul 25 at 17:08

 

 

asked Jun 12 at 20:06

beebcon
952336

 

8  
   

I found a decent fix... see the update above. –  beebcon Jul 25 at 17:10
1  
   

Look in the navigation bar for a tint color property, you should be able to change that blue color to whatever you want. –  beebcon Aug 8 at 21:43
4  
   

I hate ios upgrading sometimes because Apple never gave you a opportunity to keep your app backwards compatible. –  bagusflyer Sep 4 at 14:55
1  
   

Has anyone tried to use autolayout constraints? As far as remember, Apple iOS7 UI transition guide stated the suggestion for keeping UI compatible with iOS6 is to use autolayout. Anyway there are many changes made in UIKit, so it makes sense to read the iOS7 transition guide in full.developer.apple.com/library/prerelease/ios/documentation/… –  Hurden Sep 13 at 6:03
2  
   

If the problem is related to the view going under the status bar after hiding the navigation controller top bar I would refer to the answer by @Stunner stackoverflow.com/a/18976660/235206 as the solution –  MiKL Oct 1 at 14:53
   

add / show 7 more comments

  start a bounty

protected by 0x7fffffff Sep 13 at 12:17

This question is protected to prevent "thanks!", "me too!", or spam answers by new users. To answer it, you must have earned at least 10 reputation on this site.

11 Answers

activeoldestvotes


up vote192down voteaccepted

You can achieve this by implementing 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 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 specifywantsFullScreenLayout = 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 theextendedLayoutIncludesOpaqueBars property to NO. (The default value ofextendedLayoutIncludesOpaqueBars is NO.)

  • automaticallyAdjustsScrollViewInsets

If you don’t want a scroll view’s content insets to be automatically adjusted, setautomaticallyAdjustsScrollViewInsets to NO. (The default value ofautomaticallyAdjustsScrollViewInsets 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 oftopLayoutGuide 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


share|edit|flag

edited Oct 8 at 17:55

Mirko Catalano
1,2162529

answered Sep 13 at 11:52

Nandha
2,4691513

 

2  
   

It will not compile under iOS6. I think it should be written as performselector... –  Shmidt Sep 16 at 9:38
5  
   

Yes, Thats why I have included the selector check with if condition, if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) –  Nandha Sep 16 at 11:40
2  
   

@Julian set your window color to your view background color, i.e.: [self.window setBackgroundColor:[UIColor whiteColor]]; –  suda Sep 22 at 15:59
5  
   

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 at 14:51
4  
   

I have the same problem as @VanDuTran. edgesForExtendedLayout does not help if the navigation bar is hidden. –  fishinear Sep 24 at 16:23
   

add / show 6 more comments


up vote36down vote

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];

share|edit|flag

edited Sep 13 at 12:14

 

 

answered Sep 13 at 11:56

0x7fffffff
24.7k94878

 

7  
   

How do I do the same for just view in a .xib? –  bobics Sep 13 at 21:34
2  
   

I added one label on view and I followed your instruction but this is not working for me –  rmrahul Sep 20 at 8:08
   
   

@bobics The answer to the XIB question is, "You can't." Not through IB anyway. File a radar and hope Apple eventually addresses it. –  Answerbot Oct 10 at 17:51
   

add comment


up vote22down vote

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).


share|edit|flag

edited Nov 12 at 22:43

 

 

answered Sep 24 at 8:35

Stunner
2,96422458

 

   
   

Finally found an answer that actually works for this. Good work! –  StuartM Sep 28 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 at 14:52
   
   

Note: this will push the bottom of your view off the screen. –  Answerbot Oct 10 at 17:08
1  
   

Also, unless you are building for only iOS7, the above code will throw an error - topLayoutGuide is iOS7 only. –  Answerbot Oct 10 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 at 13:14
   

add / show 7 more comments


up vote8down vote

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 ios7if([[[[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);}

share|edit|flag

answered Sep 13 at 9:16

Magnus
1,2951023

 

   
   

what is the requirement to split 7.0 into 7 and 0 ??? @Magnus –  Leena Sep 16 at 9:57
2  
   

why can't you directly compare it with 7.0 –  Leena Sep 17 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 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 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 at 15:49 
   

add / show 2 more comments


up vote6down vote

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


share|edit|flag

answered Sep 19 at 13:45

Idan
2,5461434

 

   
   

Why the down vote? –  Idan Sep 24 at 18:16
   
   

Its not working –  SAMIR RATHOD Oct 4 at 5:54
   
   

Works for me, thanks! –  Jim True Oct 23 at 14:30
   

add comment


up vote5down vote

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

  1. Just togle 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 iOS7 in step 1)

And THE RESULT:

 


share|edit|flag

answered Sep 20 at 10:27

Riskov
13114

 

2  
   

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 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 at 15:50
   

add comment


up vote5down vote

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

share|edit|flag

answered Sep 21 at 5:18

Raj
2,46763057

  add comment

up vote3down vote

add the key View Controller-based status bar appearance from the dropdownlist as a row ininfo.plist something like this : 


share|edit|flag

edited Oct 4 at 9:11

Vaibhav Saran
2,62511526

answered Sep 23 at 21:17

N.Ramos
38611

 

   
   

Does not help... –  giuseppe Oct 3 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 at 5:06 
   

add comment


up vote3down vote

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 in 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;}}

share|edit|flag

answered Oct 1 at 15:36

werdsackjon
867

  add comment

up vote2down vote

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


share|edit|flag

answered Oct 3 at 10:28

giuseppe
726412

 

   
   

+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 at 22:32
   

add comment


up vote1down vote

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.

欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 330987132 | Go:217696290 | Python:336880185 | 做人要厚道,转载请注明出处!

时间: 2024-09-13 21:21:42

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

Liferay 使用自定义的navigation bar去取代框架默认的

我们项目组有个新的需求,就是不用Liferay 原有的navigation bar, 因为原来的navigation bar是处于<header>的下方,并且与breadcrumb进行联动,现在,我们想要我们要吧 navigation bar移动到<header>内部: Liferay默认的navigation bar如下所示: 结构如下:

顶部导航条(Top Navigation Bar)

这个可能是最简单也最常用的组件了,所以内容也不多--. 用户为了完成任务需要找到必须的内容和功能.顶部导航条在水平的紧凑的空间内提供给用户已分类内容的访问入口. 解决什么问题? 用户为了完成任务需要找到必要的内容和功能. 什么时候用? 2-12个分类 分类的标题相对较短并且可预测 分类数量基本不会变 为一个web产品展示顶级导航时 配合标签来展示二级导航 如果页面宽度很重要,用它来替代左侧导航条 通过控制导航条的状态来跟踪和展示用户当前位置很困难,成本很大时,用它来替代标签. 分类都属于一个产品

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

安卓4.1之后为全虚拟键操作,和actionbar对应,底部的虚拟键菜单称为Navigation Bar. Sumsung Galaxy Nexus 屏幕分辨率为 1280X 720,但通常的应用都会显示Navigation Bar(Back 键,Home 键等),如下图所示: 但我注意到Youtube应用在问触摸事件时,会自动隐藏Navigation Bar,全屏播放影片.网上有使用定制ROM的方式实现全屏. 但如果你想实现和Youtube类似的方法自动隐藏Navigation Bar,全屏显

用swift实现navigation bar的完全透明 &amp;amp; navigation bar中button的字体大小调整

这几天在项目中遇到的关于navigation bar的一些小问题以及解决的方法记录一下吧: 1.  完全透明navigation bar 有时候我们想要navigation viewcontroller顶部的navigation bar变得完全透明,我们首先想到是从story board下手,但是尝试了半天,也不能达到完全透明的效果 选择这里的Translucent Navigation Bar只能让bar变成那种可以稀释背景色的毛玻璃的效果,那么究竟应该如何才能把整个navigation ba

I.MX6 7&quot; navigation bar as black bar

/********************************************************************************* * I.MX6 7" navigation bar as black bar * 说明: * 这个问题一直困扰,原因是屏幕自适应的时候系统识别出错了. * * 2017-11-1 深圳 南山平山村 曾剑锋 ****************************************************************

IOS 7 Study - Displaying an Image on a Navigation Bar

ProblemYou want to display an image instead of text as the title of the current view controlleron the navigation controller SolutionUse the titleView property of the view controller's navigation item   - (void)viewDidLoad { [super viewDidLoad]; /* Cr

IOS 7 Study - Manipulating a Navigation Controller’s Array of View

ProblemYou would like to directly manipulate the array of view controllers associated with aspecific navigation controller SolutionUse the viewControllers property of the UINavigationController class to access andmodify the array of view controllers

iOS 开发库(iOS Developer Library)

iOS 开发库(iOS Developer Library) 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 以下为详尽部分,如感觉过于冗长,可移步<iOS 开发库概要(iOS Devel

从 MyEclipse 到 IntelliJ IDEA

让你摆脱鼠标,全键盘操作 从MyEclipse转战到IntelliJ IDEA的经历 我一个朋友写了一篇"从Eclipse到Android Studio"博文,于是心潮澎湃我也想一篇,分享自己用这个IDEA的一些技巧和感受. 来到公司的第一天,我的同事(也是我的师傅)就让我装IntelliJ IDEA.一开始我还不知道IntelliJ IDEA是什么,后来才知道它是一个java的集成开发环境(IDE),一个功能非常强大响应非常快速的java开发工具,号称最犀利的java IDE,重构神