I have a ViewController
which is inside a UINavigationcontroller
, but the navigationBar is hidden. When I run the app on iOS 7, the status bar shows on top of my view. Is there a way to avoid this?
I don't want to write any OS specific code.
https://i.stack.imgur.com/IxX45.png
I tried setting View controller-based status bar appearance
to NO
, but it did not fix the issue.
Xcode 5 has iOS 6/7 Deltas
which is specifically made to resolve this issue. In the storyboard, I moved my views 20 pixels down to look right on iOS 7 and in order to make it iOS 6 compatible, I changed Delta y
to -20.
https://i.stack.imgur.com/e4P7J.png
Since my storyboard is not using auto-layout, in order to resize the height of views properly on iOS 6 I had to set Delta height
as well as Delta Y
.
If you simply do NOT want any status bar at all, you need to update your plist with this data: To do this, in the plist, add those 2 settings:
<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
In iOS 7 you are expected to design your app with an overlaid transparent status bar in mind. See the new iOS 7 Weather app for example.
This is the default behaviour for UIViewController
on iOS 7. The view will be full-screen which means the status bar will cover the top of your view.
If you have a UIViewController
within a UINavigationController
and the navigationBar is visible, you can have the following code in your viewDidLoad
or have a background image for navigationBar do the trick.
self.edgesForExtendedLayout = UIRectEdgeNone;
If you have navigationBar hidden, then you have to adjust all the UIView elements by shifting 20 points. I dont't see any other solution. Use auto layout will help a little bit.
Here is the sample code for detecting the iOS version, if you want to backward compatibility.
NSUInteger DeviceSystemMajorVersion() {
static NSUInteger _deviceSystemMajorVersion = -1;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *systemVersion = [UIDevice currentDevice].systemVersion;
_deviceSystemMajorVersion = [[systemVersion componentsSeparatedByString:@"."][0] intValue];
});
return _deviceSystemMajorVersion;
}
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
Only working solution i've made by my self.
Here is my UIViewController subclass https://github.com/comonitos/ios7_overlaping
1 Subclass from UIViewController
2 Subclass your window.rootViewController from that class.
3 Voila!
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
CGRect screen = [[UIScreen mainScreen] bounds];
if (self.navigationController) {
CGRect frame = self.navigationController.view.frame;
frame.origin.y = 20;
frame.size.height = screen.size.height - 20;
self.navigationController.view.frame = frame;
} else {
if ([self respondsToSelector: @selector(containerView)]) {
UIView *containerView = (UIView *)[self performSelector: @selector(containerView)];
CGRect frame = containerView.frame;
frame.origin.y = 20;
frame.size.height = screen.size.height - 20;
containerView.frame = frame;
} else {
CGRect frame = self.view.frame;
frame.origin.y = 20;
frame.size.height = screen.size.height - 20;
self.view.frame = frame;
}
}
}
}
4 Add this to make your status bar white Just right after the [self.window makeKeyAndVisible]; !!!
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
-(UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
-(void)viewWillLayoutSubviews{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7)
{
self.view.clipsToBounds = YES;
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenHeight = 0.0;
if(UIDeviceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
screenHeight = screenRect.size.height;
else
screenHeight = screenRect.size.width;
CGRect screenFrame = CGRectMake(0, 20, self.view.frame.size.width,screenHeight-20);
CGRect viewFrame1 = [self.view convertRect:self.view.frame toView:nil];
if (!CGRectEqualToRect(screenFrame, viewFrame1))
{
self.view.frame = screenFrame;
self.view.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
}
}
Add Key in plist--- View controller-based status bar appearance : NO
To hide status bar in ios7 follow these simple steps :
In Xcode goto "Resources
" folder and open "(app name)-Info.plist file
".
check for "View controller based status bar appearance" key and set its value "NO"
check for "Status bar is initially hidden" key and set its value "YES"
If the keys are not there then you can add it by selecting "information property list
" at top and click + icon
If you wan to hide it completely and just avoid dealing with it, this works well.
-(BOOL) prefersStatusBarHidden
{
return YES;
}
reference https://stackoverflow.com/a/18873777/1030449
If using xib
s, a very easy implementation is to encapsulate all subviews inside a container view with resizing flags (which you'll already be using for 3.5" and 4" compatibility) so that the view hierarchy looks something like this
https://i.stack.imgur.com/iJkfp.png
and then in viewDidLoad
, do something like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// initializations
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) // only for iOS 7 and above
{
CGRect frame = containerView.frame;
frame.origin.y += 20;
frame.size.height -= 20;
containerView.frame = frame;
}
}
This way, the nibs need not be modified for iOS 7 compatibility. If you have a background, it can be kept outside containerView
and let it cover the whole screen.
https://i.stack.imgur.com/RsCCW.png
For Navigation Bar :
Writing this code :
self.navigationController.navigationBar.translucent = NO;
just did the trick for me.
Vincent's answer edgesForExtendedLayout worked for me.
These macros help in determining os version making it easier
// 7.0 and above
#define IS_DEVICE_RUNNING_IOS_7_AND_ABOVE() ([[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending)
// 6.0, 6.0.x, 6.1, 6.1.x
#define IS_DEVICE_RUNNING_IOS_6_OR_BELOW() ([[[UIDevice currentDevice] systemVersion] compare:@"6.2" options:NSNumericSearch] != NSOrderedDescending)
add these macros to prefix.pch file of your project and can be accessed anywhere
if(IS_DEVICE_RUNNING_IOS_7_AND_ABOVE())
{
//some iOS 7 stuff
self.edgesForExtendedLayout = UIRectEdgeNone;
}
if(IS_DEVICE_RUNNING_IOS_6_OR_BELOW())
{
// some old iOS stuff
}
I have posted my answer to another post with the same question with this one.
From Apple iOS7 transition Guide, https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TransitionGuide/AppearanceCustomization.html#//apple_ref/doc/uid/TP40013174-CH15-SW1
Specifically automaticallyAdjustsScrollViewInsets=YES
and set self.edgesForExtendedLayout = UIRectEdgeNone
works for me when I don't want to the overlap and I have a tableviewcontroller
.
If you want "Use Autolayout" to be enabled at any cost place the following code in viewdidload.
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7)
{
self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = NO;
self.automaticallyAdjustsScrollViewInsets = NO;
}
My status bar and navigation bar overlap after return from landscape view of YTPlayer. Here is my solution after trying @comonitos' version but not work on my iOS 8
- (void)fixNavigationBarPosition {
if (self.navigationController) {
CGRect frame = self.navigationController.navigationBar.frame;
if (frame.origin.y != 20.f) {
frame.origin.y = 20.f;
self.navigationController.navigationBar.frame = frame;
}
}
}
Just call this function whenever you want to fix the position of navigation bar. I called on YTPlayerViewDelegate's playerView:didChangeToState:
- (void)playerView:(YTPlayerView *)playerView didChangeToState:(YTPlayerState)state {
switch (state) {
case kYTPlayerStatePaused:
case kYTPlayerStateEnded:
[self fixNavigationBarPosition];
break;
default:
}
}
Success story sharing