IOS7-状态栏与视图重叠

我有一个 ViewController是在一个 UINavigationcontroller,但导航栏是隐藏的。当我在 iOS7上运行这个应用程序时,状态栏显示在我的视图上方。有办法避免这种情况吗?

我不想写任何特定于操作系统的代码。

Enter image description here

我尝试将 View controller-based status bar appearance设置为 NO,但它没有解决这个问题。

110894 次浏览

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

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.

enter image description here

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.

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.

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
}

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

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

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

For Navigation Bar :

Writing this code :

self.navigationController.navigationBar.translucent = NO;

just did the trick for me.

If using xibs, 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

xib heirarchy

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.

This is all that is needed to remove the status bar. enter image description here

-(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

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:
}
}